Compare commits
6 Commits
v2.0.3-bet
...
v2.0.4-bet
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e908c45cf2 | ||
![]() |
c37e934f42 | ||
![]() |
41f91956b8 | ||
![]() |
8b2bd5ce79 | ||
![]() |
28e4151157 | ||
![]() |
66d45293e6 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v2.0.4-beta (2017-12-29)
|
||||||
|
|
||||||
|
* Monitoring:
|
||||||
|
* Fix: Current activity cards duplicating on the homepage.
|
||||||
|
* Notifications:
|
||||||
|
* Fix: Concurrent stream notifications being sent when there is an incorrect number of streams.
|
||||||
|
* UI:
|
||||||
|
* New: Info pages for collections.
|
||||||
|
* New: Button to test Plex Web URL override.
|
||||||
|
* Fix: Library and User pages return to the correct tab when pressing back.
|
||||||
|
|
||||||
|
|
||||||
## v2.0.3-beta (2017-12-25)
|
## v2.0.3-beta (2017-12-25)
|
||||||
|
|
||||||
* Monitoring:
|
* Monitoring:
|
||||||
|
@@ -1808,7 +1808,8 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
#children-list, #search-results-list {
|
.children-list,
|
||||||
|
.search-results-list {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
@@ -1874,15 +1875,15 @@ a:hover .item-children-poster {
|
|||||||
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
|
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
|
||||||
z-index: -2;
|
z-index: -2;
|
||||||
}
|
}
|
||||||
.item-children-poster-face.season-poster {
|
.item-children-poster-face.poster-item {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 225px;
|
height: 225px;
|
||||||
}
|
}
|
||||||
.item-children-poster-face.episode-poster {
|
.item-children-poster-face.episode-item {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
height: 140px;
|
height: 140px;
|
||||||
}
|
}
|
||||||
.item-children-poster-face.album-poster {
|
.item-children-poster-face.cover-item {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
@@ -1915,15 +1916,13 @@ a:hover .item-children-poster {
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
.item-children-instance-text-wrapper.season-item {
|
.item-children-instance-text-wrapper.poster-item,
|
||||||
|
.item-children-instance-text-wrapper.cover-item {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
.item-children-instance-text-wrapper.episode-item {
|
.item-children-instance-text-wrapper.episode-item {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
.item-children-instance-text-wrapper.album-item {
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
.item-children-instance-text-wrapper h3 {
|
.item-children-instance-text-wrapper h3 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 5px 3px 0 3px;
|
padding: 5px 3px 0 3px;
|
||||||
|
@@ -235,7 +235,12 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var create_instances = [];
|
||||||
|
var activity_ready = true;
|
||||||
|
|
||||||
function getCurrentActivity() {
|
function getCurrentActivity() {
|
||||||
|
activity_ready = false;
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_activity',
|
url: 'get_activity',
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
@@ -298,6 +303,7 @@
|
|||||||
|
|
||||||
// Create a new instance if it doesn't exist
|
// Create a new instance if it doesn't exist
|
||||||
if (!(instance.length)) {
|
if (!(instance.length)) {
|
||||||
|
create_instances.push(key);
|
||||||
getActivityInstance(key);
|
getActivityInstance(key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -501,6 +507,8 @@
|
|||||||
$('#currentActivityHeader').text('');
|
$('#currentActivityHeader').text('');
|
||||||
$('#currentActivity').html('<div id="dashboard-no-activity" class="text-muted">Nothing is currently being played.</div>');
|
$('#currentActivity').html('<div id="dashboard-no-activity" class="text-muted">Nothing is currently being played.</div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
activity_ready = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -520,13 +528,20 @@
|
|||||||
$('#activity-instance-' + session_key + ' [data-toggle=tooltip]').tooltip({ container: 'body', placement: 'right', delay: 50 });
|
$('#activity-instance-' + session_key + ' [data-toggle=tooltip]').tooltip({ container: 'body', placement: 'right', delay: 50 });
|
||||||
$('#terminate-button-' + session_key).tooltip('destroy').tooltip({ container: 'body', placement: 'left', delay: 50 });
|
$('#terminate-button-' + session_key).tooltip('destroy').tooltip({ container: 'body', placement: 'left', delay: 50 });
|
||||||
lockScroll('#activity-instance-' + session_key + ' .dashboard-activity-info-scroller');
|
lockScroll('#activity-instance-' + session_key + ' .dashboard-activity-info-scroller');
|
||||||
|
|
||||||
|
var index = create_instances.indexOf(session_key);
|
||||||
|
if (index > -1) {
|
||||||
|
create_instances.splice(index, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentActivity();
|
getCurrentActivity();
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
if (!(create_instances.length) && activity_ready) {
|
||||||
getCurrentActivity();
|
getCurrentActivity();
|
||||||
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
setInterval(function(){
|
setInterval(function(){
|
||||||
|
@@ -80,7 +80,7 @@ DOCUMENTATION :: END
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="summary-navbar-list">
|
<div class="summary-navbar-list">
|
||||||
<ul class="list-unstyled breadcrumb">
|
<ul class="list-unstyled breadcrumb">
|
||||||
% if data['media_type'] == 'movie':
|
% if data['media_type'] in ('movie', 'collection'):
|
||||||
<li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
|
<li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
|
||||||
<li class="active">${data['title']}</li>
|
<li class="active">${data['title']}</li>
|
||||||
% elif data['media_type'] == 'show':
|
% elif data['media_type'] == 'show':
|
||||||
@@ -116,9 +116,9 @@ DOCUMENTATION :: END
|
|||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<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'] or 'https://app.plex.tv/desktop'}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="_blank" title="View in 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 in Plex Web">
|
||||||
% else:
|
% else:
|
||||||
<a href="${config['pms_web_url'] or 'https://app.plex.tv/desktop'}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View in Plex Web">
|
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View in Plex Web">
|
||||||
% endif
|
% endif
|
||||||
% if data['media_type'] == 'episode':
|
% if data['media_type'] == 'episode':
|
||||||
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=art);">
|
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=art);">
|
||||||
@@ -151,7 +151,7 @@ DOCUMENTATION :: END
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-content-title">
|
<div class="summary-content-title">
|
||||||
% if data['media_type'] in ('movie', 'show', 'artist'):
|
% if data['media_type'] in ('movie', 'show', 'artist', 'collection'):
|
||||||
<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="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></h1>
|
<h1> </h1><h1><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></h1>
|
||||||
@@ -175,7 +175,7 @@ DOCUMENTATION :: END
|
|||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
% if data['media_type'] == 'movie':
|
% if data['media_type'] == 'movie':
|
||||||
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 305px;">
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 305px;">
|
||||||
% elif data['media_type'] == 'show' or data['media_type'] == 'season':
|
% elif data['media_type'] in ('show', 'season', 'collection'):
|
||||||
<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;">
|
||||||
@@ -235,6 +235,8 @@ DOCUMENTATION :: END
|
|||||||
Aired <strong> <span id="airdate">${data['originally_available_at']}</span></strong>
|
Aired <strong> <span id="airdate">${data['originally_available_at']}</span></strong>
|
||||||
% elif data['media_type'] == 'album' or data['media_type'] == 'track':
|
% elif data['media_type'] == 'album' or data['media_type'] == 'track':
|
||||||
Released <strong> ${data['year']}</strong>
|
Released <strong> ${data['year']}</strong>
|
||||||
|
% elif data['media_type'] == 'collection':
|
||||||
|
Year <strong> ${data['min_year']} - ${data['max_year']}</strong>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-content-details-tag">
|
<div class="summary-content-details-tag">
|
||||||
@@ -308,51 +310,65 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
% if data['media_type'] == 'show':
|
% if data['media_type'] == 'show':
|
||||||
<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">
|
||||||
<span>Season List for <strong>${data['title']}</strong></span>
|
<span>Season List for <strong>${data['title']}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class="table-card-back">
|
||||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading season list...</div>
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading season list...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% elif data['media_type'] == 'season':
|
% elif data['media_type'] == 'season':
|
||||||
<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">
|
||||||
<span>Episode List for <strong>${data['title']}</strong></span>
|
<span>Episode List for <strong>${data['title']}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class="table-card-back">
|
||||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading episode list...</div>
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading episode list...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% elif data['media_type'] == 'artist':
|
% elif data['media_type'] == 'artist':
|
||||||
<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">
|
||||||
<span>Album List for <strong>${data['title']}</strong></span>
|
<span>Album List for <strong>${data['title']}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class="table-card-back">
|
||||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading album list...</div>
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading album list...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% elif data['media_type'] == 'album':
|
% elif data['media_type'] == 'album':
|
||||||
<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">
|
||||||
<span>Track List for <strong>${data['title']}</strong></span>
|
<span>Track List for <strong>${data['title']}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class="table-card-back">
|
||||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading track list...</div>
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading track list...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
% elif data['media_type'] == 'collection':
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="table-card-header">
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>Movies in <strong>${data['title']}</strong> collection</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-card-back">
|
||||||
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading movies list...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="collection-related-list-container" style="display: none;">
|
||||||
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
% if data['media_type'] != 'collection':
|
||||||
<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">
|
||||||
<span>Watch History for <strong>${data['title']}</strong></span>
|
<span>Watch History for <strong>${data['title']}</strong></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -420,6 +436,7 @@ DOCUMENTATION :: END
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -562,6 +579,7 @@ DOCUMENTATION :: END
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
|
% if data['media_type'] != 'collection':
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
get_history();
|
get_history();
|
||||||
@@ -638,7 +656,8 @@ DOCUMENTATION :: END
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% if data['media_type'] in ('show', 'season', 'artist', 'album'):
|
% endif
|
||||||
|
% if data['media_type'] in ('show', 'season', 'artist', 'album', 'collection'):
|
||||||
<script>
|
<script>
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_item_children',
|
url: 'get_item_children',
|
||||||
@@ -646,7 +665,24 @@ DOCUMENTATION :: END
|
|||||||
async: true,
|
async: true,
|
||||||
data: { rating_key : "${data['rating_key']}" },
|
data: { rating_key : "${data['rating_key']}" },
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#children-list").html(xhr.responseText); }
|
$("#children-list").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
% endif
|
||||||
|
% if data['media_type'] == 'collection':
|
||||||
|
<script>
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_item_children_related',
|
||||||
|
type: 'GET',
|
||||||
|
async: true,
|
||||||
|
data: {
|
||||||
|
rating_key : "${data['rating_key']}",
|
||||||
|
title: "${data['title']}"
|
||||||
|
},
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#collection-related-list-container").html(xhr.responseText).show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
|
@@ -37,13 +37,42 @@ DOCUMENTATION :: END
|
|||||||
% else:
|
% else:
|
||||||
<li>
|
<li>
|
||||||
% endif
|
% endif
|
||||||
%if data['children_type'] == 'season':
|
% if data['children_type'] == 'movie':
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">
|
||||||
|
<div class="item-children-poster">
|
||||||
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
% if _session['user_group'] == 'admin':
|
||||||
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
|
</h3>
|
||||||
|
<h3 class="text-muted">${child['year']}</h3>
|
||||||
|
</div>
|
||||||
|
% elif data['children_type'] == 'show':
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">
|
||||||
|
<div class="item-children-poster">
|
||||||
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
% if _session['user_group'] == 'admin':
|
||||||
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
% elif data['children_type'] == 'season':
|
||||||
<a href="info?rating_key=${child['rating_key']}" title="Season ${child['media_index']}">
|
<a href="info?rating_key=${child['rating_key']}" title="Season ${child['media_index']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
% if child['thumb']:
|
% if child['thumb']:
|
||||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);">
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);">
|
||||||
% else:
|
% else:
|
||||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=450&fallback=poster);">
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=450&fallback=poster);">
|
||||||
% endif
|
% endif
|
||||||
<div class="item-children-card-overlay">
|
<div class="item-children-card-overlay">
|
||||||
<div class="item-children-overlay-text">
|
<div class="item-children-overlay-text">
|
||||||
@@ -59,7 +88,7 @@ DOCUMENTATION :: END
|
|||||||
% elif data['children_type'] == 'episode':
|
% elif data['children_type'] == 'episode':
|
||||||
<a href="info?rating_key=${child['rating_key']}" title="Episode ${child['media_index']}">
|
<a href="info?rating_key=${child['rating_key']}" title="Episode ${child['media_index']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face episode-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=500&height=250&fallback=art);">
|
<div class="item-children-poster-face episode-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=500&height=250&fallback=art);">
|
||||||
<div class="item-children-card-overlay">
|
<div class="item-children-card-overlay">
|
||||||
<div class="item-children-overlay-text">
|
<div class="item-children-overlay-text">
|
||||||
Episode ${child['media_index']}
|
Episode ${child['media_index']}
|
||||||
@@ -79,13 +108,13 @@ DOCUMENTATION :: END
|
|||||||
% elif data['children_type'] == 'album':
|
% elif data['children_type'] == 'album':
|
||||||
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></div>
|
<div class="item-children-poster-face cover-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></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>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<div class="item-children-instance-text-wrapper album-item">
|
<div class="item-children-instance-text-wrapper cover-item">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
99
data/interfaces/default/info_collection_list.html
Normal file
99
data/interfaces/default/info_collection_list.html
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<%doc>
|
||||||
|
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
|
||||||
|
|
||||||
|
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
|
||||||
|
|
||||||
|
Filename: info_collection_list.html
|
||||||
|
Version: 0.1
|
||||||
|
Variable names: data [list]
|
||||||
|
|
||||||
|
data :: Usable parameters
|
||||||
|
|
||||||
|
== Global keys ==
|
||||||
|
children_type Returns the type of children in the array.
|
||||||
|
children_count Returns the number of episodes in the array.
|
||||||
|
children_list Returns an array of episodes.
|
||||||
|
|
||||||
|
data['children_list'] :: Usable paramaters
|
||||||
|
|
||||||
|
== Global keys ==
|
||||||
|
rating_key Returns the unique identifier for the media item.
|
||||||
|
media_index Returns the episode number.
|
||||||
|
title Returns the name of the episode.
|
||||||
|
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||||
|
parent_thumb Returns the location of the item's parent thumbnail. Use with pms_image_proxy.
|
||||||
|
|
||||||
|
DOCUMENTATION :: END
|
||||||
|
</%doc>
|
||||||
|
|
||||||
|
% if data != None:
|
||||||
|
<%
|
||||||
|
types = ('movie', 'show', 'artist', 'album')
|
||||||
|
headers = {'movie': 'Movies',
|
||||||
|
'show': 'TV Shows',
|
||||||
|
'season': 'Seasons',
|
||||||
|
'episode': 'Episodes',
|
||||||
|
'artist': 'Artists',
|
||||||
|
'album': 'Albums',
|
||||||
|
'track': 'Tracks',
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
% for media_type in types:
|
||||||
|
% if data['results_list'][media_type]:
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="table-card-header">
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>${headers[media_type]} in <strong>${title}</strong> collection</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-card-back">
|
||||||
|
<div id="children-list" class="children-list">
|
||||||
|
<div class="item-children-wrapper">
|
||||||
|
<ul class="item-children-instance list-unstyled">
|
||||||
|
% for child in data['results_list'][media_type]:
|
||||||
|
<li>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">
|
||||||
|
<div class="item-children-poster">
|
||||||
|
% if media_type in ('artist', 'album'):
|
||||||
|
<div class="item-children-poster-face cover-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></div>
|
||||||
|
% else:
|
||||||
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
% endif
|
||||||
|
% if _session['user_group'] == 'admin':
|
||||||
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
% if media_type == 'artist':
|
||||||
|
<div class="item-children-instance-text-wrapper cover-item">
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
% elif media_type == 'album':
|
||||||
|
<div class="item-children-instance-text-wrapper cover-item">
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['parent_rating_key']}" title="${child['parent_title']}">${child['parent_title']}</a>
|
||||||
|
</h3>
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
|
<h3>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" title="${child['title']}">${child['title']}</a>
|
||||||
|
</h3>
|
||||||
|
<h3 class="text-muted">${child['year']}</h3>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</li>
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
% endif
|
@@ -54,6 +54,31 @@ DOCUMENTATION :: END
|
|||||||
|
|
||||||
% if data != None:
|
% if data != None:
|
||||||
% if data['results_count'] > 0:
|
% if data['results_count'] > 0:
|
||||||
|
% if 'collection' in data['results_list'] and data['results_list']['collection']:
|
||||||
|
<div class="item-children-wrapper">
|
||||||
|
<div class="item-children-section-title">
|
||||||
|
<h4>Collections</h4>
|
||||||
|
</div>
|
||||||
|
<ul class="item-children-instance list-unstyled">
|
||||||
|
% for child in data['results_list']['collection']:
|
||||||
|
<li>
|
||||||
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
|
<div class="item-children-poster">
|
||||||
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
% if _session['user_group'] == 'admin':
|
||||||
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
|
<h3 title="${child['title']}">${child['title']}</h3>
|
||||||
|
<h3 class="text-muted">${child['min_year']} - ${child['max_year']}</h3>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
% if 'movie' in data['results_list'] and data['results_list']['movie']:
|
% if 'movie' in data['results_list'] and data['results_list']['movie']:
|
||||||
<div class="item-children-wrapper">
|
<div class="item-children-wrapper">
|
||||||
<div class="item-children-section-title">
|
<div class="item-children-section-title">
|
||||||
@@ -64,12 +89,12 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></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>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="item-children-instance-text-wrapper season-item">
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
<h3 title="${child['title']}">${child['title']}</h3>
|
<h3 title="${child['title']}">${child['title']}</h3>
|
||||||
<h3 class="text-muted">${child['year']}</h3>
|
<h3 class="text-muted">${child['year']}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,12 +114,12 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></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>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="item-children-instance-text-wrapper season-item">
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
<h3 title="${child['title']}">${child['title']}</h3>
|
<h3 title="${child['title']}">${child['title']}</h3>
|
||||||
<h3 class="text-muted">${child['year']}</h3>
|
<h3 class="text-muted">${child['year']}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -114,12 +139,12 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="item-children-poster-face poster-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450&fallback=poster);"></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>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="item-children-instance-text-wrapper season-item">
|
<div class="item-children-instance-text-wrapper poster-item">
|
||||||
<h3 title="${child['parent_title']}">${child['parent_title']}</h3>
|
<h3 title="${child['parent_title']}">${child['parent_title']}</h3>
|
||||||
<h3 class="text-muted">S${child['media_index']}</h3>
|
<h3 class="text-muted">S${child['media_index']}</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -139,7 +164,7 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face episode-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=500&height=250&fallback=art);"></div>
|
<div class="item-children-poster-face episode-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=500&height=250&fallback=art);"></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>
|
||||||
% endif
|
% endif
|
||||||
@@ -165,7 +190,7 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></div>
|
<div class="item-children-poster-face cover-item style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></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>
|
||||||
% endif
|
% endif
|
||||||
@@ -189,7 +214,7 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></div>
|
<div class="item-children-poster-face cover-item" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300&fallback=cover);"></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>
|
||||||
% endif
|
% endif
|
||||||
@@ -214,7 +239,7 @@ DOCUMENTATION :: END
|
|||||||
<li>
|
<li>
|
||||||
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
<a href="info?rating_key=${child['rating_key']}" id="${child['rating_key']}">
|
||||||
<div class="item-children-poster">
|
<div class="item-children-poster">
|
||||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=300&fallback=cover);">
|
<div class="item-children-poster-face cover-item" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=300&fallback=cover);">
|
||||||
<div class="item-children-card-overlay">
|
<div class="item-children-card-overlay">
|
||||||
<div class="item-children-overlay-text">
|
<div class="item-children-overlay-text">
|
||||||
Track ${child['media_index']}
|
Track ${child['media_index']}
|
||||||
|
@@ -71,11 +71,11 @@ DOCUMENTATION :: END
|
|||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info-nav">
|
<div class="user-info-nav">
|
||||||
<ul class="user-info-nav">
|
<ul class="user-info-nav" role="tablist">
|
||||||
<li class="active"><a href="#profile" data-toggle="tab">Profile</a></li>
|
<li class="active"><a href="#tabs-profile" role="tab" data-toggle="tab">Profile</a></li>
|
||||||
<li><a id="history-tab-btn" href="#libraryHistory" data-toggle="tab">History</a></li>
|
<li><a id="history-tab-btn" href="#tabs-history" role="tab" data-toggle="tab">History</a></li>
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
<li><a id="media-info-tab-btn" href="#libraryMediaInfo" data-toggle="tab">Media Info</a></li>
|
<li><a id="media-info-tab-btn" href="#tabs-mediainfo" role="tab" data-toggle="tab">Media Info</a></li>
|
||||||
% endif
|
% endif
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,7 +83,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane active" id="profile">
|
<div role="tabpanel" class="tab-pane active" id="tabs-profile">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -169,7 +169,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="libraryHistory">
|
<div role="tabpanel" class="tab-pane" id="tabs-history">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -221,7 +221,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="libraryMediaInfo">
|
<div role="tabpanel" class="tab-pane" id="tabs-mediainfo">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -366,27 +366,8 @@ DOCUMENTATION :: END
|
|||||||
<script src="${http_root}js/tables/history_table.js${cache_param}"></script>
|
<script src="${http_root}js/tables/history_table.js${cache_param}"></script>
|
||||||
<script src="${http_root}js/tables/media_info_table.js${cache_param}"></script>
|
<script src="${http_root}js/tables/media_info_table.js${cache_param}"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
$("#edit-library-tooltip").tooltip();
|
$.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
|
||||||
|
|
||||||
// Populate watch time stats
|
|
||||||
$.ajax({
|
|
||||||
url: 'library_watch_time_stats',
|
|
||||||
async: true,
|
|
||||||
data: { section_id: section_id },
|
|
||||||
complete: function(xhr, status) {
|
|
||||||
$("#library-time-stats").html(xhr.responseText);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Populate user stats
|
|
||||||
$.ajax({
|
|
||||||
url: 'library_user_stats',
|
|
||||||
async: true,
|
|
||||||
data: { section_id: section_id },
|
|
||||||
complete: function(xhr, status) {
|
|
||||||
$("#library-user-stats").html(xhr.responseText);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadHistoryTable() {
|
function loadHistoryTable() {
|
||||||
@@ -410,14 +391,10 @@ DOCUMENTATION :: END
|
|||||||
clearSearchButton('history_table-SID-${data["section_id"]}', history_table);
|
clearSearchButton('history_table-SID-${data["section_id"]}', history_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
$( "#history-tab-btn" ).one( "click", function() {
|
$('a[href="#tabs-history"]').on('shown.bs.tab', function() {
|
||||||
loadHistoryTable();
|
loadHistoryTable();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|
||||||
$.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
|
|
||||||
});
|
|
||||||
|
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
function loadMediaInfoTable() {
|
function loadMediaInfoTable() {
|
||||||
// Build media info table
|
// Build media info table
|
||||||
@@ -440,7 +417,7 @@ DOCUMENTATION :: END
|
|||||||
clearSearchButton('media_info_table-SID-${data["section_id"]}', media_info_table);
|
clearSearchButton('media_info_table-SID-${data["section_id"]}', media_info_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
$( "#media-info-tab-btn" ).one( "click", function() {
|
$('a[href="#tabs-mediainfo"]').on('shown.bs.tab', function() {
|
||||||
loadMediaInfoTable();
|
loadMediaInfoTable();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -452,6 +429,8 @@ DOCUMENTATION :: END
|
|||||||
refresh_table = false;
|
refresh_table = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#edit-library-tooltip").tooltip();
|
||||||
|
|
||||||
// Load edit library modal
|
// Load edit library modal
|
||||||
$("#toggle-edit-library-modal").click(function() {
|
$("#toggle-edit-library-modal").click(function() {
|
||||||
$("#edit-library-tooltip").tooltip('hide');
|
$("#edit-library-tooltip").tooltip('hide');
|
||||||
@@ -620,6 +599,41 @@ DOCUMENTATION :: END
|
|||||||
$("#recently-added-page-right").removeClass("disabled");
|
$("#recently-added-page-right").removeClass("disabled");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
// Javascript to enable link to tab
|
||||||
|
var hash = document.location.hash;
|
||||||
|
var prefix = "tab_";
|
||||||
|
if (hash) {
|
||||||
|
$('.user-info-nav a[href='+hash.replace(prefix,"")+']').tab('show').trigger('show.bs.tab');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change hash for page-reload
|
||||||
|
$('.user-info-nav a').on('shown.bs.tab', function (e) {
|
||||||
|
window.location.hash = e.target.hash.replace("#", "#" + prefix);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate watch time stats
|
||||||
|
$.ajax({
|
||||||
|
url: 'library_watch_time_stats',
|
||||||
|
async: true,
|
||||||
|
data: { section_id: section_id },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#library-time-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate user stats
|
||||||
|
$.ajax({
|
||||||
|
url: 'library_user_stats',
|
||||||
|
async: true,
|
||||||
|
data: { section_id: section_id },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#library-user-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class='table-card-back'>
|
||||||
<div id="search-results-list"><i class="fa fa-refresh fa-spin"></i> Loading search results...</div>
|
<div id="search-results-list" class="search-results-list"><i class="fa fa-refresh fa-spin"></i> Loading search results...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
@@ -559,7 +559,7 @@
|
|||||||
<p class="help-block">Enable to have Tautulli check if remote access to the Plex Media Server goes down.</p>
|
<p class="help-block">Enable to have Tautulli check if remote access to the Plex Media Server goes down.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group has-feedback" id="pms-ip-group">
|
<div class="form-group has-feedback" id="pms_ip_group">
|
||||||
<label for="pms_ip">Plex IP or Hostname</label>
|
<label for="pms_ip">Plex IP or Hostname</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@@ -569,7 +569,7 @@
|
|||||||
<button class="btn btn-form" type="button" id="verify_server_button">Verify Server</button>
|
<button class="btn btn-form" type="button" id="verify_server_button">Verify Server</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="form-control-feedback" id="pms-verify" aria-hidden="true" style="display: none; right: 110px;"></span>
|
<span class="form-control-feedback" id="pms_verify" aria-hidden="true" style="display: none; right: 110px;"></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="pms_ip_error" class="alert alert-danger settings-alert" role="alert"></div>
|
<div id="pms_ip_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -607,7 +607,12 @@
|
|||||||
<label for="pms_logs_folder">Plex Web URL</label>
|
<label for="pms_logs_folder">Plex Web URL</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<input type="text" class="form-control" id="pms_web_url" name="pms_web_url" value="${config['pms_web_url']}" size="30" data-parsley-trigger="change" data-parsley-pattern="^https?:\/\/.+\/web\/index\.html$|^https:\/\/app.plex.tv\/desktop$" data-parsley-errors-container="#pms_web_url_error" data-parsley-error-message="Invalid Plex Web URL." required>
|
<div class="input-group">
|
||||||
|
<input type="text" class="form-control" id="pms_web_url" name="pms_web_url" value="${config['pms_web_url']}" size="30" data-parsley-trigger="change" data-parsley-pattern="^https?:\/\/\S+$|^https:\/\/app.plex.tv\/desktop$" data-parsley-errors-container="#pms_web_url_error" data-parsley-error-message="Invalid Plex Web URL.">
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn btn-form" type="button" id="test_pms_web_button">Test URL</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="pms_web_url_error" class="alert alert-danger settings-alert" role="alert"></div>
|
<div id="pms_web_url_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1580,6 +1585,17 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function preSaveChecks(_callback) {
|
||||||
|
if ($("#pms_identifier").val() == "") {
|
||||||
|
verifyServer();
|
||||||
|
}
|
||||||
|
verifyPMSWebURL();
|
||||||
|
|
||||||
|
if (_callback) {
|
||||||
|
_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Alert the user that their changes require a restart.
|
// Alert the user that their changes require a restart.
|
||||||
function postSaveChecks() {
|
function postSaveChecks() {
|
||||||
if (serverChanged || authChanged || httpChanged || directoryChanged) {
|
if (serverChanged || authChanged || httpChanged || directoryChanged) {
|
||||||
@@ -1609,11 +1625,7 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('.save-button').click(function() {
|
$('.save-button').click(function() {
|
||||||
if ($("#pms_identifier").val() == "") {
|
preSaveChecks(function () { saveSettings() });
|
||||||
verifyServer(function () { saveSettings() });
|
|
||||||
} else {
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
initConfigCheckbox('#api_enabled');
|
initConfigCheckbox('#api_enabled');
|
||||||
@@ -1758,43 +1770,45 @@ $(document).ready(function() {
|
|||||||
var pms_identifier = $("#pms_identifier").val();
|
var pms_identifier = $("#pms_identifier").val();
|
||||||
var pms_ssl = $("#pms_ssl").is(':checked') ? 1 : 0;
|
var pms_ssl = $("#pms_ssl").is(':checked') ? 1 : 0;
|
||||||
var pms_is_remote = $("#pms_is_remote").is(':checked') ? 1 : 0;
|
var pms_is_remote = $("#pms_is_remote").is(':checked') ? 1 : 0;
|
||||||
|
|
||||||
if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
|
if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
|
||||||
$("#pms-verify").html('<i class="fa fa-refresh fa-spin"></i>');
|
$("#pms_verify").html('<i class="fa fa-refresh fa-spin"></i>').fadeIn('fast');
|
||||||
$('#pms-verify').fadeIn('fast');
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_server_id',
|
url: 'get_server_id',
|
||||||
data : { hostname: pms_ip, port: pms_port, identifier: pms_identifier, ssl: pms_ssl, remote: pms_is_remote },
|
data: {
|
||||||
|
hostname: pms_ip,
|
||||||
|
port: pms_port,
|
||||||
|
identifier: pms_identifier,
|
||||||
|
ssl: pms_ssl,
|
||||||
|
remote: pms_is_remote
|
||||||
|
},
|
||||||
cache: true,
|
cache: true,
|
||||||
async: true,
|
async: true,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
$("#pms-verify").html('<i class="fa fa-close"></i>');
|
$("#pms_verify").html('<i class="fa fa-close"></i>').fadeIn('fast');
|
||||||
$('#pms-verify').fadeIn('fast');
|
$("#pms_ip_group").addClass("has-error");
|
||||||
$("#pms-ip-group").addClass("has-error");
|
|
||||||
},
|
},
|
||||||
success: function (json) {
|
success: function (json) {
|
||||||
var machine_identifier = json;
|
var machine_identifier = json;
|
||||||
if (machine_identifier) {
|
if (machine_identifier) {
|
||||||
$("#pms_identifier").val(machine_identifier);
|
$("#pms_identifier").val(machine_identifier);
|
||||||
$("#pms-verify").html('<i class="fa fa-check"></i>');
|
$("#pms_verify").html('<i class="fa fa-check"></i>').fadeIn('fast');
|
||||||
$('#pms-verify').fadeIn('fast');
|
$("#pms_ip_group").removeClass("has-error");
|
||||||
$("#pms-ip-group").removeClass("has-error");
|
|
||||||
|
|
||||||
if (_callback) {
|
if (_callback) {
|
||||||
_callback();
|
_callback();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$("#pms-verify").html('<i class="fa fa-close"></i>');
|
$("#pms_verify").html('<i class="fa fa-close"></i>').fadeIn('fast');
|
||||||
$('#pms-verify').fadeIn('fast');
|
$("#pms_ip_group").addClass("has-error");
|
||||||
$("#pms-ip-group").addClass("has-error");
|
|
||||||
showMsg('<i class="fa fa-exclamation-circle"></i> Could not verify your server.', false, true, 5000, true)
|
showMsg('<i class="fa fa-exclamation-circle"></i> Could not verify your server.', false, true, 5000, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$("#pms-verify").html('<i class="fa fa-close"></i>');
|
$("#pms_verify").html('<i class="fa fa-close"></i>').fadeIn('fast');
|
||||||
$('#pms-verify').fadeIn('fast');
|
$("#pms_ip_group").addClass("has-error");
|
||||||
$("#pms-ip-group").addClass("has-error");
|
|
||||||
showMsg('<i class="fa fa-exclamation-circle"></i> Could not verify your server.', false, true, 5000, true)
|
showMsg('<i class="fa fa-exclamation-circle"></i> Could not verify your server.', false, true, 5000, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1804,11 +1818,21 @@ $(document).ready(function() {
|
|||||||
verifyServer();
|
verifyServer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function verifyPMSWebURL() {
|
||||||
|
var pms_web_url = $.trim($("#pms_web_url").val());
|
||||||
|
$("#pms_web_url").val(pms_web_url || 'https://app.plex.tv/desktop');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#test_pms_web_button').on('click', function(){
|
||||||
|
var pms_web_url = $.trim($("#pms_web_url").val());
|
||||||
|
window.open(pms_web_url, '_blank');
|
||||||
|
});
|
||||||
|
|
||||||
// Plex.tv auth token fetch
|
// Plex.tv auth token fetch
|
||||||
$("#get-pms-auth-token").click(function() {
|
$("#get-pms-auth-token").click(function() {
|
||||||
$("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i> Fetching token...');
|
$("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i> Fetching token...');
|
||||||
var pms_username = $("#pms_username").val().trim();
|
var pms_username = $.trim($("#pms_username").val());
|
||||||
var pms_password = $("#pms_password").val().trim();
|
var pms_password = $.trim($("#pms_password").val());
|
||||||
if ((pms_username !== '') && (pms_password !== '')) {
|
if ((pms_username !== '') && (pms_password !== '')) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
|
@@ -61,19 +61,19 @@ DOCUMENTATION :: END
|
|||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info-nav">
|
<div class="user-info-nav">
|
||||||
<ul class="user-info-nav">
|
<ul class="user-info-nav" role="tablist">
|
||||||
<li class="active"><a href="#profile" data-toggle="tab">Profile</a></li>
|
<li class="active"><a href="#tabs-profile" role="tab" data-toggle="tab">Profile</a></li>
|
||||||
<li><a id="history-tab-btn" href="#userHistory" data-toggle="tab">History</a></li>
|
<li><a id="history-tab-btn" href="#tabs-history" role="tab" data-toggle="tab">History</a></li>
|
||||||
<li><a id="sync-tab-btn" href="#userSyncItems" data-toggle="tab">Synced Items</a></li>
|
<li><a id="sync-tab-btn" href="#tabs-synceditems" role="tab" data-toggle="tab">Synced Items</a></li>
|
||||||
<li><a id="ip-tab-btn" href="#userAddresses" data-toggle="tab">IP Addresses</a></li>
|
<li><a id="ip-tab-btn" href="#tabs-ipaddresses" role="tab" data-toggle="tab">IP Addresses</a></li>
|
||||||
<li><a id="login-tab-btn" href="#userLogins" data-toggle="tab">Tautulli Logins</a></li>
|
<li><a id="login-tab-btn" href="#tabs-tautullilogins" role="tab" data-toggle="tab">Tautulli Logins</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane active" id="profile">
|
<div role="tabpanel" class="tab-pane active" id="tabs-profile">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -134,7 +134,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="userHistory">
|
<div role="tabpanel" class="tab-pane" id="tabs-history">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -200,7 +200,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="userSyncItems">
|
<div role="tabpanel" class="tab-pane" id="tabs-synceditems">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -240,7 +240,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="userAddresses">
|
<div role="tabpanel" class="tab-pane" id="tabs-ipaddresses">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -271,7 +271,7 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="userLogins">
|
<div role="tabpanel" class="tab-pane" id="tabs-tautullilogins">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@@ -369,14 +369,7 @@ DOCUMENTATION :: END
|
|||||||
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
% if data:
|
% if data:
|
||||||
<script src="${http_root}js/moment-with-locale.js"></script>
|
|
||||||
<script src="${http_root}js/tables/history_table.js${cache_param}"></script>
|
|
||||||
<script src="${http_root}js/tables/user_ips.js${cache_param}"></script>
|
|
||||||
<script src="${http_root}js/tables/sync_table.js${cache_param}"></script>
|
|
||||||
<script src="${http_root}js/tables/login_logs.js${cache_param}"></script>
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
|
||||||
|
|
||||||
% if str(data['user_id']).isdigit():
|
% if str(data['user_id']).isdigit():
|
||||||
var user_id = ${data['user_id']};
|
var user_id = ${data['user_id']};
|
||||||
% else:
|
% else:
|
||||||
@@ -384,27 +377,20 @@ DOCUMENTATION :: END
|
|||||||
% endif
|
% endif
|
||||||
|
|
||||||
var username = '${data['username'].replace("'", "\\'")}';
|
var username = '${data['username'].replace("'", "\\'")}';
|
||||||
|
</script>
|
||||||
$("#edit-user-tooltip").tooltip();
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
|
<script src="${http_root}js/tables/history_table.js${cache_param}"></script>
|
||||||
// Populate watch time stats
|
<script src="${http_root}js/tables/user_ips.js${cache_param}"></script>
|
||||||
$.ajax({
|
<script src="${http_root}js/tables/sync_table.js${cache_param}"></script>
|
||||||
url: 'user_watch_time_stats',
|
<script src="${http_root}js/tables/login_logs.js${cache_param}"></script>
|
||||||
async: true,
|
<script>
|
||||||
data: { user_id: user_id, user: username },
|
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
complete: function(xhr, status) {
|
$.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
|
||||||
$("#user-time-stats").html(xhr.responseText);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Populate platform stats
|
$('a[href="#tabs-profile"]').on('shown.bs.tab', function() {
|
||||||
$.ajax({
|
var media_type = null;
|
||||||
url: 'user_player_stats',
|
loadHistoryTable(media_type);
|
||||||
async: true,
|
|
||||||
data: { user_id: user_id, user: username },
|
|
||||||
complete: function(xhr, status) {
|
|
||||||
$("#user-player-stats").html(xhr.responseText);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadHistoryTable(media_type) {
|
function loadHistoryTable(media_type) {
|
||||||
@@ -437,29 +423,12 @@ DOCUMENTATION :: END
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$( "#history-tab-btn" ).one( "click", function() {
|
$('a[href="#tabs-history"]').on('shown.bs.tab', function() {
|
||||||
var media_type = null;
|
var media_type = null;
|
||||||
loadHistoryTable(media_type);
|
loadHistoryTable(media_type);
|
||||||
});
|
});
|
||||||
|
|
||||||
$( "#ip-tab-btn" ).one( "click", function() {
|
$('a[href="#tabs-synceditems"]').on('shown.bs.tab', function() {
|
||||||
// Build user IP table
|
|
||||||
user_ip_table_options.ajax = {
|
|
||||||
url: 'get_user_ips',
|
|
||||||
type: 'post',
|
|
||||||
data: function ( d ) {
|
|
||||||
return {
|
|
||||||
json_data: JSON.stringify( d ),
|
|
||||||
user_id: user_id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user_ip_table = $('#user_ip_table-UID-${data["user_id"]}').DataTable(user_ip_table_options);
|
|
||||||
|
|
||||||
clearSearchButton('user_ip_table-UID-${data["user_id"]}', user_ip_table);
|
|
||||||
});
|
|
||||||
|
|
||||||
$( "#sync-tab-btn" ).one( "click", function() {
|
|
||||||
// Build user sync table
|
// Build user sync table
|
||||||
sync_table_options.ajax = {
|
sync_table_options.ajax = {
|
||||||
url: 'get_sync',
|
url: 'get_sync',
|
||||||
@@ -476,7 +445,24 @@ DOCUMENTATION :: END
|
|||||||
clearSearchButton('sync_table-UID-${data["user_id"]}', sync_table);
|
clearSearchButton('sync_table-UID-${data["user_id"]}', sync_table);
|
||||||
});
|
});
|
||||||
|
|
||||||
$( "#login-tab-btn" ).one( "click", function() {
|
$('a[href="#tabs-ipaddresses"]').on('shown.bs.tab', function() {
|
||||||
|
// Build user IP table
|
||||||
|
user_ip_table_options.ajax = {
|
||||||
|
url: 'get_user_ips',
|
||||||
|
type: 'post',
|
||||||
|
data: function ( d ) {
|
||||||
|
return {
|
||||||
|
json_data: JSON.stringify( d ),
|
||||||
|
user_id: user_id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
user_ip_table = $('#user_ip_table-UID-${data["user_id"]}').DataTable(user_ip_table_options);
|
||||||
|
|
||||||
|
clearSearchButton('user_ip_table-UID-${data["user_id"]}', user_ip_table);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('a[href="#tabs-tautullilogins"]').on('shown.bs.tab', function() {
|
||||||
// Build user login table
|
// Build user login table
|
||||||
login_log_table_options.ajax = {
|
login_log_table_options.ajax = {
|
||||||
url: 'get_user_logins',
|
url: 'get_user_logins',
|
||||||
@@ -493,11 +479,9 @@ DOCUMENTATION :: END
|
|||||||
clearSearchButton('login_log_table-UID-${data["user_id"]}', login_log_table);
|
clearSearchButton('login_log_table-UID-${data["user_id"]}', login_log_table);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
|
||||||
$.fn.dataTable.tables({ visible: true, api: true }).columns.adjust();
|
|
||||||
});
|
|
||||||
|
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
|
$("#edit-user-tooltip").tooltip();
|
||||||
|
|
||||||
// Load edit user modal
|
// Load edit user modal
|
||||||
$("#toggle-edit-user-modal").click(function() {
|
$("#toggle-edit-user-modal").click(function() {
|
||||||
$("#edit-user-tooltip").tooltip('hide');
|
$("#edit-user-tooltip").tooltip('hide');
|
||||||
@@ -611,6 +595,41 @@ DOCUMENTATION :: END
|
|||||||
$("#recently-watched-page-right").removeClass("disabled");
|
$("#recently-watched-page-right").removeClass("disabled");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
// Javascript to enable link to tab
|
||||||
|
var hash = document.location.hash;
|
||||||
|
var prefix = "tab_";
|
||||||
|
if (hash) {
|
||||||
|
$('.user-info-nav a[href='+hash.replace(prefix,"")+']').tab('show').trigger('show.bs.tab');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change hash for page-reload
|
||||||
|
$('.user-info-nav a').on('shown.bs.tab', function (e) {
|
||||||
|
window.location.hash = e.target.hash.replace("#", "#" + prefix);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate watch time stats
|
||||||
|
$.ajax({
|
||||||
|
url: 'user_watch_time_stats',
|
||||||
|
async: true,
|
||||||
|
data: { user_id: user_id, user: username },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#user-time-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate platform stats
|
||||||
|
$.ajax({
|
||||||
|
url: 'user_player_stats',
|
||||||
|
async: true,
|
||||||
|
data: { user_id: user_id, user: username },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#user-player-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
|
@@ -1104,7 +1104,7 @@ class DataFactory(object):
|
|||||||
if str(rating_key).isdigit():
|
if str(rating_key).isdigit():
|
||||||
poster_key = rating_key
|
poster_key = rating_key
|
||||||
elif metadata:
|
elif metadata:
|
||||||
if metadata['media_type'] in ('movie', 'show', 'artist'):
|
if metadata['media_type'] in ('movie', 'show', 'artist', 'collection'):
|
||||||
poster_key = metadata['rating_key']
|
poster_key = metadata['rating_key']
|
||||||
elif metadata['media_type'] in ('season', 'album'):
|
elif metadata['media_type'] in ('season', 'album'):
|
||||||
poster_key = metadata['rating_key']
|
poster_key = metadata['rating_key']
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import bleach
|
import bleach
|
||||||
|
from collections import Counter
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
import json
|
import json
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
@@ -145,9 +146,16 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if notify_action == 'on_concurrent':
|
if notify_action == 'on_concurrent':
|
||||||
ap = activity_processor.ActivityProcessor()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
user_sessions = ap.get_sessions(user_id=stream_data['user_id'],
|
result = pms_connect.get_current_activity()
|
||||||
ip_address=plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP)
|
|
||||||
|
user_sessions = []
|
||||||
|
if result:
|
||||||
|
user_sessions = [s for s in result['sessions'] if s['user_id'] == stream_data['user_id']]
|
||||||
|
|
||||||
|
if plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP:
|
||||||
|
return len(Counter(s['ip_address'] for s in user_sessions)) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
|
||||||
|
else:
|
||||||
return len(user_sessions) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
|
return len(user_sessions) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
|
||||||
|
|
||||||
elif notify_action == 'on_newdevice':
|
elif notify_action == 'on_newdevice':
|
||||||
@@ -504,7 +512,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
|
|||||||
|
|
||||||
# Build Plex URL
|
# Build Plex URL
|
||||||
metadata['plex_url'] = '{web_url}#!/server/{pms_identifier}/details?key=%2Flibrary%2Fmetadata%2F{rating_key}'.format(
|
metadata['plex_url'] = '{web_url}#!/server/{pms_identifier}/details?key=%2Flibrary%2Fmetadata%2F{rating_key}'.format(
|
||||||
web_url=plexpy.CONFIG.PMS_WEB_URL or 'https://app.plex.tv/desktop',
|
web_url=plexpy.CONFIG.PMS_WEB_URL,
|
||||||
pms_identifier=plexpy.CONFIG.PMS_IDENTIFIER,
|
pms_identifier=plexpy.CONFIG.PMS_IDENTIFIER,
|
||||||
rating_key=rating_key)
|
rating_key=rating_key)
|
||||||
|
|
||||||
|
@@ -257,6 +257,23 @@ class PmsConnect(object):
|
|||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_children_list_related(self, rating_key='', output_format=''):
|
||||||
|
"""
|
||||||
|
Return list of related children in requested collection item.
|
||||||
|
|
||||||
|
Parameters required: rating_key { ratingKey of parent }
|
||||||
|
Optional parameters: output_format { dict, json }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
uri = '/hubs/metadata/' + rating_key + '/related'
|
||||||
|
request = self.request_handler.make_request(uri=uri,
|
||||||
|
proto=self.protocol,
|
||||||
|
request_type='GET',
|
||||||
|
output_format=output_format)
|
||||||
|
|
||||||
|
return request
|
||||||
|
|
||||||
def get_childrens_list(self, rating_key='', output_format=''):
|
def get_childrens_list(self, rating_key='', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of children in requested library item.
|
Return list of children in requested library item.
|
||||||
@@ -414,7 +431,7 @@ class PmsConnect(object):
|
|||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
uri = '/hubs/search?query=' + urllib.quote(query.encode('utf8')) + '&limit=' + limit
|
uri = '/hubs/search?query=' + urllib.quote(query.encode('utf8')) + '&limit=' + limit + '&includeCollections=1'
|
||||||
request = self.request_handler.make_request(uri=uri,
|
request = self.request_handler.make_request(uri=uri,
|
||||||
proto=self.protocol,
|
proto=self.protocol,
|
||||||
request_type='GET',
|
request_type='GET',
|
||||||
@@ -607,7 +624,7 @@ class PmsConnect(object):
|
|||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_metadata: %s." % e)
|
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_metadata_details: %s." % e)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
metadata = {}
|
metadata = {}
|
||||||
@@ -1039,6 +1056,50 @@ class PmsConnect(object):
|
|||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elif metadata_type == 'collection':
|
||||||
|
metadata = {'media_type': metadata_type,
|
||||||
|
'sub_media_type': helpers.get_xml_attr(metadata_main, 'subtype'),
|
||||||
|
'section_id': section_id,
|
||||||
|
'library_name': library_name,
|
||||||
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
|
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
|
||||||
|
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
|
||||||
|
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||||
|
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||||
|
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||||
|
'sort_title': helpers.get_xml_attr(metadata_main, 'titleSort'),
|
||||||
|
'media_index': helpers.get_xml_attr(metadata_main, 'index'),
|
||||||
|
'parent_media_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
|
||||||
|
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
|
||||||
|
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
|
||||||
|
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
|
||||||
|
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
|
||||||
|
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
|
||||||
|
'audience_rating': helpers.get_xml_attr(metadata_main, 'audienceRating'),
|
||||||
|
'user_rating': helpers.get_xml_attr(metadata_main, 'userRating'),
|
||||||
|
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
|
||||||
|
'year': helpers.get_xml_attr(metadata_main, 'year'),
|
||||||
|
'min_year': helpers.get_xml_attr(metadata_main, 'minYear'),
|
||||||
|
'max_year': helpers.get_xml_attr(metadata_main, 'maxYear'),
|
||||||
|
'thumb': helpers.get_xml_attr(metadata_main, 'thumb').split('?')[0],
|
||||||
|
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
|
||||||
|
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
|
||||||
|
'art': helpers.get_xml_attr(metadata_main, 'art'),
|
||||||
|
'banner': helpers.get_xml_attr(metadata_main, 'banner'),
|
||||||
|
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
|
||||||
|
'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'),
|
||||||
|
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
|
||||||
|
'child_count': helpers.get_xml_attr(metadata_main, 'childCount'),
|
||||||
|
'directors': directors,
|
||||||
|
'writers': writers,
|
||||||
|
'actors': actors,
|
||||||
|
'genres': genres,
|
||||||
|
'labels': labels,
|
||||||
|
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
@@ -1795,7 +1856,6 @@ class PmsConnect(object):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_item_children(self, rating_key=''):
|
def get_item_children(self, rating_key=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated children list.
|
Return processed and validated children list.
|
||||||
@@ -1836,8 +1896,11 @@ class PmsConnect(object):
|
|||||||
for result in result_data:
|
for result in result_data:
|
||||||
children_output = {'section_id': section_id,
|
children_output = {'section_id': section_id,
|
||||||
'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
|
||||||
|
'parent_rating_key': helpers.get_xml_attr(result, 'parentRatingKey'),
|
||||||
'media_index': helpers.get_xml_attr(result, 'index'),
|
'media_index': helpers.get_xml_attr(result, 'index'),
|
||||||
'title': helpers.get_xml_attr(result, 'title'),
|
'title': helpers.get_xml_attr(result, 'title'),
|
||||||
|
'parent_title': helpers.get_xml_attr(result, 'parentTitle'),
|
||||||
|
'year': helpers.get_xml_attr(result, 'year'),
|
||||||
'thumb': helpers.get_xml_attr(result, 'thumb'),
|
'thumb': helpers.get_xml_attr(result, 'thumb'),
|
||||||
'parent_thumb': helpers.get_xml_attr(a, 'thumb'),
|
'parent_thumb': helpers.get_xml_attr(a, 'thumb'),
|
||||||
'duration': helpers.get_xml_attr(result, 'duration')
|
'duration': helpers.get_xml_attr(result, 'duration')
|
||||||
@@ -1852,6 +1915,72 @@ class PmsConnect(object):
|
|||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
def get_item_children_related(self, rating_key=''):
|
||||||
|
"""
|
||||||
|
Return processed and validated children list.
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
children_data = self.get_children_list_related(rating_key, output_format='xml')
|
||||||
|
|
||||||
|
try:
|
||||||
|
xml_head = children_data.getElementsByTagName('MediaContainer')
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_item_children_related: %s." % e)
|
||||||
|
return []
|
||||||
|
|
||||||
|
children_results_list = {'movie': [],
|
||||||
|
'show': [],
|
||||||
|
'season': [],
|
||||||
|
'episode': [],
|
||||||
|
'artist': [],
|
||||||
|
'album': [],
|
||||||
|
'track': [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for a in xml_head:
|
||||||
|
section_id = helpers.get_xml_attr(a, 'librarySectionID')
|
||||||
|
hubs = a.getElementsByTagName('Hub')
|
||||||
|
|
||||||
|
for h in hubs:
|
||||||
|
size = helpers.get_xml_attr(h, 'size')
|
||||||
|
media_type = helpers.get_xml_attr(h, 'type')
|
||||||
|
title = helpers.get_xml_attr(h, 'title')
|
||||||
|
hub_identifier = helpers.get_xml_attr(h, 'hubIdentifier')
|
||||||
|
|
||||||
|
if size == '0' or not hub_identifier.startswith('collection.related') or \
|
||||||
|
media_type not in children_results_list.keys():
|
||||||
|
continue
|
||||||
|
|
||||||
|
result_data = []
|
||||||
|
|
||||||
|
if h.getElementsByTagName('Video'):
|
||||||
|
result_data = h.getElementsByTagName('Video')
|
||||||
|
if h.getElementsByTagName('Directory'):
|
||||||
|
result_data = h.getElementsByTagName('Directory')
|
||||||
|
if h.getElementsByTagName('Track'):
|
||||||
|
result_data = h.getElementsByTagName('Track')
|
||||||
|
|
||||||
|
for result in result_data:
|
||||||
|
children_output = {'section_id': section_id,
|
||||||
|
'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
|
||||||
|
'parent_rating_key': helpers.get_xml_attr(result, 'parentRatingKey'),
|
||||||
|
'media_index': helpers.get_xml_attr(result, 'index'),
|
||||||
|
'title': helpers.get_xml_attr(result, 'title'),
|
||||||
|
'parent_title': helpers.get_xml_attr(result, 'parentTitle'),
|
||||||
|
'year': helpers.get_xml_attr(result, 'year'),
|
||||||
|
'thumb': helpers.get_xml_attr(result, 'thumb'),
|
||||||
|
'parent_thumb': helpers.get_xml_attr(a, 'thumb'),
|
||||||
|
'duration': helpers.get_xml_attr(result, 'duration')
|
||||||
|
}
|
||||||
|
children_results_list[media_type].append(children_output)
|
||||||
|
|
||||||
|
output = {'results_count': sum(len(s) for s in children_results_list.items()),
|
||||||
|
'results_list': children_results_list,
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
def get_servers_info(self):
|
def get_servers_info(self):
|
||||||
"""
|
"""
|
||||||
Return the list of local servers.
|
Return the list of local servers.
|
||||||
@@ -2237,7 +2366,8 @@ class PmsConnect(object):
|
|||||||
'episode': [],
|
'episode': [],
|
||||||
'artist': [],
|
'artist': [],
|
||||||
'album': [],
|
'album': [],
|
||||||
'track': []
|
'track': [],
|
||||||
|
'collection': []
|
||||||
}
|
}
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
PLEXPY_BRANCH = "beta"
|
PLEXPY_BRANCH = "beta"
|
||||||
PLEXPY_RELEASE_VERSION = "v2.0.3-beta"
|
PLEXPY_RELEASE_VERSION = "v2.0.4-beta"
|
||||||
|
@@ -3588,7 +3588,7 @@ class WebInterface(object):
|
|||||||
def get_item_children(self, rating_key='', **kwargs):
|
def get_item_children(self, rating_key='', **kwargs):
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_item_children(rating_key)
|
result = pms_connect.get_item_children(rating_key=rating_key)
|
||||||
|
|
||||||
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, title="Children List")
|
||||||
@@ -3596,6 +3596,18 @@ class WebInterface(object):
|
|||||||
logger.warn(u"Unable to retrieve data for get_item_children.")
|
logger.warn(u"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")
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
@requireAuth()
|
||||||
|
def get_item_children_related(self, rating_key='', title='', **kwargs):
|
||||||
|
|
||||||
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
result = pms_connect.get_item_children_related(rating_key=rating_key)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return serve_template(templatename="info_collection_list.html", data=result, title=title)
|
||||||
|
else:
|
||||||
|
return serve_template(templatename="info_collection_list.html", data=None, title=title)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.json_out()
|
@cherrypy.tools.json_out()
|
||||||
@requireAuth()
|
@requireAuth()
|
||||||
|
Reference in New Issue
Block a user