mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-12 00:06:07 -07:00
Merge branch 'dev'
# Conflicts: # data/interfaces/default/info.html
This commit is contained in:
commit
6b75a55ce8
25 changed files with 2678 additions and 1039 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,5 +1,22 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.1.6 (2015-09-06)
|
||||||
|
|
||||||
|
* Home stats cards are now expandable to show multiple items. Configurable in settings. Thanks @JonnyWong.
|
||||||
|
* Completely redesigned media info pages. Thanks @JonnyWong.
|
||||||
|
* Redesigned activity pane to match Plex Web more closely. Thanks @JonnyWong.
|
||||||
|
* New Library stats on home page, shows total item counts per library. Thanks @JonnyWong.
|
||||||
|
* New last watched card in home stats. Shows last watched items. Thanks @JonnyWong.
|
||||||
|
* Improved some layout issues on mobile devices. Thanks @JonnyWong.
|
||||||
|
* Fixed issue where some clip/channel items are reported as episodes and causing exceptions.
|
||||||
|
* Many styling improvements and fixes. Thanks @JonnyWong.
|
||||||
|
* Fixed incorrect sort on home stats platform count by duration. Thanks @JonnyWong.
|
||||||
|
* Fix issue where user refresh would continually be called as "Local" user didn't exist in database.
|
||||||
|
* Fixed styling on graph stream modal. Thanks @JonnyWong.
|
||||||
|
* Fixed some issues with users page editing. Thanks @JonnyWong.
|
||||||
|
* Fix error page when clicking through to an item that no longer exists.
|
||||||
|
|
||||||
|
|
||||||
## v1.1.5 (2015-08-27)
|
## v1.1.5 (2015-08-27)
|
||||||
|
|
||||||
* Fix git tag being one release behind.
|
* Fix git tag being one release behind.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%
|
<%
|
||||||
import plexpy
|
import plexpy
|
||||||
from plexpy import version
|
from plexpy import version
|
||||||
%>
|
%>
|
||||||
|
@ -52,7 +52,7 @@ from plexpy import version
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="home">
|
<a class="navbar-brand" href="home">
|
||||||
<img alt="PlexPy" src="interfaces/default/images/logo-plexpy@2x.png" height="40px">
|
<img alt="PlexPy" src="interfaces/default/images/logo-plexpy@2x.png" height="40">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
||||||
|
@ -99,7 +99,9 @@ from plexpy import version
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${next.headerIncludes()}
|
${next.headerIncludes()}
|
||||||
${next.body()}
|
<div class="body-container">
|
||||||
|
${next.body()}
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="interfaces/default/js/jquery-2.1.4.min.js"></script>
|
<script src="interfaces/default/js/jquery-2.1.4.min.js"></script>
|
||||||
<script src="interfaces/default/js/bootstrap3/bootstrap.min.js"></script>
|
<script src="interfaces/default/js/bootstrap3/bootstrap.min.js"></script>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,8 +28,10 @@ user Returns the name of the user owning the session.
|
||||||
user_id Returns the Plex user id if available.
|
user_id Returns the Plex user id if available.
|
||||||
machine_id Returns the machine id of the players being used.
|
machine_id Returns the machine id of the players being used.
|
||||||
friendly_name Returns the friendlly name of the user owning the session.
|
friendly_name Returns the friendlly name of the user owning the session.
|
||||||
|
user_thumb Returns the profile picture of the user owning the session.
|
||||||
state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'.
|
state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'.
|
||||||
title Returns the name of the episode, movie or music track.
|
title Returns the name of the episode, movie or music track.
|
||||||
|
year Returns the year of the episode, movie, or clip.
|
||||||
player Returns the name of the platform used to play the stream.
|
player Returns the name of the platform used to play the stream.
|
||||||
platform Returns the type of platform used to play the stream.
|
platform Returns the type of platform used to play the stream.
|
||||||
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
|
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
|
||||||
|
@ -61,159 +63,166 @@ DOCUMENTATION :: END
|
||||||
% if data is not None:
|
% if data is not None:
|
||||||
% if data['stream_count'] != '0':
|
% if data['stream_count'] != '0':
|
||||||
% for a in data['sessions']:
|
% for a in data['sessions']:
|
||||||
<div class="instance" id="instance-${a['session_key']}">
|
<div class="dashboard-instance" id="instance-${a['session_key']}">
|
||||||
<div class="poster">
|
% if a['type'] == 'movie' or a['type'] == 'episode':
|
||||||
<div class="dashboard-activity-poster-face">
|
<a href="info?item_id=${a['rating_key']}">
|
||||||
|
% endif
|
||||||
|
<div class="dashboard-activity-poster">
|
||||||
|
<script>console.log('${a['indexes']}');</script>
|
||||||
% if a['type'] == 'movie' and not a['indexes']:
|
% if a['type'] == 'movie' and not a['indexes']:
|
||||||
<img src="pms_image_proxy?img=${a['art']}&width=410&height=230"/>
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
||||||
|
% elif a['type'] == 'episode' and not a['indexes']:
|
||||||
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
||||||
% elif a['indexes']:
|
% elif a['indexes']:
|
||||||
<img onload="fadeIn(this)" src="pms_image_proxy?img=${a['bif_thumb']}&width=300&height=169" style="display: none;"/>
|
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div>
|
||||||
% else:
|
% else:
|
||||||
% if a['type'] == 'track':
|
% if a['type'] == 'track':
|
||||||
<div class="dashboard-activity-poster-music-bg" style="background-image: url('pms_image_proxy?img=${a['thumb']}&width=300&height=300');"></div>
|
<div class="dashboard-activity-cover-face-bg" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300);"></div>
|
||||||
% endif
|
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300);"></div>
|
||||||
% if a['type'] == 'clip':
|
% elif a['type'] == 'clip':
|
||||||
<img src="${a['thumb']}"/>
|
% if a['art'][:4] == 'http':
|
||||||
% else:
|
<div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div>
|
||||||
<img src="pms_image_proxy?img=${a['thumb']}&width=410&height=230&fallback=cover"/>
|
% elif a['thumb'][:4] == 'http':
|
||||||
% endif
|
<div class="dashboard-activity-poster-face" style="background-image: url(${a['thumb']});"></div>
|
||||||
% endif
|
|
||||||
<div class="dashboard-activity-poster-info-bar">
|
|
||||||
<div class="dashboard-activity-poster-info-text">
|
|
||||||
% if a['type'] == 'track':
|
|
||||||
Track ${a['media_index']}
|
|
||||||
% elif a['type'] == 'episode':
|
|
||||||
Season ${a['parent_media_index']}, Episode ${a['media_index']}
|
|
||||||
% else:
|
% else:
|
||||||
${a['title']}
|
% if a['art']:
|
||||||
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
|
||||||
|
% else:
|
||||||
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);"></div>
|
||||||
|
% endif
|
||||||
% endif
|
% endif
|
||||||
|
% else:
|
||||||
|
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
<div class="dashboard-activity-button-info">
|
||||||
|
<button type="button" class="btn btn-activity-info btn-lg" data-target="#stream-${a['session_key']}">
|
||||||
|
<i class="fa fa-info-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="stream-${a['session_key']}" class="dashboard-activity-info-details-overlay">
|
||||||
|
<div class="dashboard-activity-info-details-content">
|
||||||
|
<div class="dashboard-activity-info-platform" id="platform-${a['session_key']}">
|
||||||
|
<strong>${a['player']}</strong><br />
|
||||||
|
% if a['state'] == 'playing':
|
||||||
|
State <strong>Playing</strong>
|
||||||
|
% elif a['state'] == 'paused':
|
||||||
|
State <strong>Paused</strong>
|
||||||
|
% elif a['state'] == 'buffering':
|
||||||
|
State <strong>Buffering</strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
% if a['type'] == 'track':
|
||||||
|
% if a['audio_decision'] == 'direct play':
|
||||||
|
Stream <strong>Direct Play</strong>
|
||||||
|
% else:
|
||||||
|
Stream <strong>Transcoding</strong>
|
||||||
|
% endif
|
||||||
|
<br />
|
||||||
|
% if a['audio_decision'] == 'direct play':
|
||||||
|
Audio <strong>Direct Play (${a['audio_codec']}) (${a['audio_channels']}ch)</strong>
|
||||||
|
% elif a['audio_decision'] == 'Copy':
|
||||||
|
Audio <strong>Direct Stream (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
|
||||||
|
% elif a['audio_decision'] != 'transcode':
|
||||||
|
Audio <strong>Transcode (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
|
||||||
|
% endif
|
||||||
|
% elif a['type'] == 'episode' or a['type'] == 'movie' or a['type'] == 'clip':
|
||||||
|
% if a['video_decision'] == 'direct play':
|
||||||
|
Stream <strong>Direct Play</strong>
|
||||||
|
% else:
|
||||||
|
Stream <strong>Transcoding</strong>
|
||||||
|
% endif
|
||||||
|
<br />
|
||||||
|
% if a['video_decision'] == 'direct play':
|
||||||
|
Video <strong>Direct Play (${a['video_codec']}) (${a['width']}x${a['height']})</strong>
|
||||||
|
% elif a['video_decision'] == 'copy':
|
||||||
|
Video <strong>Direct Stream (${a['transcode_video_codec']}) (${a['width']}x${a['height']})</strong>
|
||||||
|
% elif a['video_decision'] == 'transcode':
|
||||||
|
Video <strong>Transcode (${a['transcode_video_codec']}) (${a['transcode_width']}x${a['transcode_height']})</strong>
|
||||||
|
% endif
|
||||||
|
<br />
|
||||||
|
% if a['audio_decision'] == 'direct play':
|
||||||
|
Audio <strong>Direct Play (${a['audio_codec']}) (${a['audio_channels']}ch)</strong>
|
||||||
|
% elif a['audio_decision'] == 'copy':
|
||||||
|
Audio <strong>Direct Stream (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
|
||||||
|
% elif a['audio_decision'] == 'transcode':
|
||||||
|
Audio <strong>Transcode (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-activity-poster-info-bar">
|
||||||
<div class="dashboard-activity-poster-info-time">
|
<div class="dashboard-activity-poster-info-time">
|
||||||
<span class="progress_time">${a['progress']}</span>/<span class="progress_time">${a['duration']}</span>
|
<span class="progress_time">${a['progress']}</span>/<span class="progress_time">${a['duration']}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='dashboard-activity-metadata-wrapper'>
|
% if a['type'] == 'movie' or a['type'] == 'episode':
|
||||||
<div class='dashboard-activity-instance-overlay'>
|
</a>
|
||||||
<div class='dashboard-activity-metadata-progress-minutes'>
|
% endif
|
||||||
<div class='activity-progress'>
|
<div class="dashboard-activity-progress">
|
||||||
<div class="bar" style="width: ${a['progress_percent']}%">${a['progress_percent']}%</div>
|
<div class="dashboard-activity-progress-bar">
|
||||||
</div>
|
<div class="bar" style="width: ${a['progress_percent']}%">${a['progress_percent']}%</div>
|
||||||
</div>
|
|
||||||
<div class="dashboard-activity-metadata-platform" data-toggle="tooltip" data-placement="right" title data-title="${a['player']}" id="platform-${a['session_key']}">
|
|
||||||
</div>
|
|
||||||
<div class="dashboard-activity-metadata-user">
|
|
||||||
% if a['user_id']:
|
|
||||||
<a href="user?user_id=${a['user_id']}">${a['friendly_name']}</a> is ${a['state']}
|
|
||||||
% else:
|
|
||||||
<a href="user?user=${a['user']}">${a['friendly_name']}</a> is ${a['state']}
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
<div class="dashboard-activity-metadata-title">
|
|
||||||
% if a['type'] == 'episode':
|
|
||||||
<a href="info?item_id=${a['rating_key']}">${a['grandparent_title']} - ${a['title']}</a>
|
|
||||||
% elif a['type'] == 'movie':
|
|
||||||
<a href="info?item_id=${a['rating_key']}">${a['title']}</a>
|
|
||||||
% elif a['type'] == 'clip':
|
|
||||||
${a['title']}
|
|
||||||
% elif a['type'] == 'track':
|
|
||||||
${a['grandparent_title']} - ${a['title']}
|
|
||||||
% else:
|
|
||||||
${a['grandparent_title']} - ${a['title']}
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="stream-${a['session_key']}" class="collapse out">
|
|
||||||
<div class='dashboard-activity-info-details-overlay'>
|
|
||||||
<div class='dashboard-activity-info-details-content'>
|
|
||||||
% if a['type'] == 'track':
|
|
||||||
Artist: <strong>${a['grandparent_title']}</strong>
|
|
||||||
<br>
|
|
||||||
Album: <strong>${a['parent_title']}</strong>
|
|
||||||
<br>
|
|
||||||
% endif
|
|
||||||
% if a['state'] == 'playing':
|
|
||||||
State: <strong>Playing</strong>
|
|
||||||
% elif a['state'] == 'paused':
|
|
||||||
State: <strong>Paused</strong>
|
|
||||||
% elif a['state'] == 'buffering':
|
|
||||||
State: <strong>Buffering</strong>
|
|
||||||
% endif
|
|
||||||
<br>
|
|
||||||
% if a['type'] == 'track':
|
|
||||||
% if a['audio_decision'] == 'direct play':
|
|
||||||
Stream: <strong>Direct Play</strong>
|
|
||||||
% else:
|
|
||||||
Stream: <strong>Transcoding</strong>
|
|
||||||
% endif
|
|
||||||
<br/>
|
|
||||||
% if a['audio_decision'] != 'direct play':
|
|
||||||
Audio: <strong>${a['transcode_audio_codec']} (${a['transcode_audio_channels']}ch)</strong>
|
|
||||||
% elif a['audio_decision'] == 'direct play':
|
|
||||||
Audio: <strong>${a['audio_codec']} (${a['audio_channels']}ch)</strong>
|
|
||||||
% endif
|
|
||||||
% elif a['type'] == 'episode' or a['type'] == 'movie' or a['type'] == 'clip':
|
|
||||||
% if a['video_decision'] == 'direct play':
|
|
||||||
Stream: <strong>Direct Play</strong>
|
|
||||||
% else:
|
|
||||||
Stream: <strong>Transcoding</strong>
|
|
||||||
% endif
|
|
||||||
<br/>
|
|
||||||
% if a['video_decision'] != 'direct play':
|
|
||||||
Video: <strong>${a['video_decision']} (${a['transcode_video_codec']})
|
|
||||||
(${a['transcode_width']}x${a['transcode_height']})</strong>
|
|
||||||
% elif a['audio_decision'] == 'direct play':
|
|
||||||
Video: <strong>${a['video_decision']} (${a['video_codec']})
|
|
||||||
(${a['width']}x${a['height']})</strong>
|
|
||||||
% endif
|
|
||||||
<br/>
|
|
||||||
% if a['audio_decision'] != 'direct play':
|
|
||||||
Audio: <strong>${a['audio_decision']} ${a['transcode_audio_codec']} (${a['transcode_audio_channels']}ch)</strong>
|
|
||||||
% elif a['audio_decision'] == 'direct play':
|
|
||||||
Audio: <strong>${a['audio_codec']} (${a['audio_channels']}ch)</strong>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dashboard-activity-button-info">
|
<div class="dashboard-activity-metadata-wrapper">
|
||||||
<button type="button" class="btn btn-activity-info btn-sm" data-toggle="collapse" data-target="#stream-${a['session_key']}">
|
<a href="user?user_id=${a['user_id']}">
|
||||||
<i class='fa fa-info-circle'></i>
|
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
|
||||||
</button>
|
</a>
|
||||||
</div>
|
<div class="dashboard-activity-metadata-title">
|
||||||
|
% if a['type'] == 'episode':
|
||||||
|
<a href="info?item_id=${a['rating_key']}">${a['grandparent_title']} - ${a['title']}</a>
|
||||||
|
% elif a['type'] == 'movie':
|
||||||
|
<a href="info?item_id=${a['rating_key']}">${a['title']}</a>
|
||||||
|
% elif a['type'] == 'clip':
|
||||||
|
${a['title']}
|
||||||
|
% elif a['type'] == 'track':
|
||||||
|
${a['grandparent_title']} - ${a['title']}
|
||||||
|
% else:
|
||||||
|
${a['grandparent_title']} - ${a['title']}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-activity-metadata-subtitle">
|
||||||
|
% if a['type'] == 'episode':
|
||||||
|
S${a['parent_media_index']} · E${a['media_index']}
|
||||||
|
% elif a['type'] == 'movie':
|
||||||
|
${a['year']}
|
||||||
|
% elif a['type'] == 'track':
|
||||||
|
${a['parent_title']}
|
||||||
|
% else:
|
||||||
|
${a['year']}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-activity-metadata-user">
|
||||||
|
% if a['user_id']:
|
||||||
|
<a href="user?user_id=${a['user_id']}">${a['friendly_name']}</a>
|
||||||
|
% else:
|
||||||
|
<a href="user?user=${a['user']}">${a['friendly_name']}</a>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$("#platform-${a['session_key']}").html("<img src='" + getPlatformImagePath('${a['platform']}') + "'>");
|
$("#platform-${a['session_key']}").prepend("<div class='dashboard-activity-info-platform-box' style='background-image: url(" + getPlatformImagePath('${a['platform']}') + ");'>");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
% endfor
|
% endfor
|
||||||
<script>
|
<script>
|
||||||
// When using bif indexes make the image transition a little smoother.
|
// When using bif indexes make the image transition a little smoother.
|
||||||
function fadeIn(obj) {
|
$('.bif').each(function() {
|
||||||
$(obj).fadeIn(450);
|
$(this).fadeIn(1000);
|
||||||
}
|
});
|
||||||
|
|
||||||
// Convert timestamps to readable times
|
// Convert timestamps to readable times
|
||||||
$('.progress_time').each(function(index) {
|
$('.progress_time').each(function(index) {
|
||||||
$(this).html(millisecondsToMinutes($(this).text(), false));
|
$(this).html(millisecondsToMinutes($(this).text(), false));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hide the info bar on page load
|
// Show/Hide activity info
|
||||||
$('.dashboard-activity-poster-info-bar').hide();
|
$('.btn-activity-info').on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
// When mouse over the activity pane, show an info bar with extra info.
|
$($(this).attr('data-target')).toggle();
|
||||||
$('.dashboard-activity-poster-face').mouseenter(function() {
|
|
||||||
$('.dashboard-activity-poster-info-bar', this).slideDown('fast');
|
|
||||||
});
|
|
||||||
$('.dashboard-activity-poster-face').mouseleave(function() {
|
|
||||||
$('.dashboard-activity-poster-info-bar', this).slideUp('fast');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tooltips
|
|
||||||
$('.dashboard-activity-metadata-platform').each(function() {
|
|
||||||
$(this).tooltip();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% else:
|
% else:
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
data: { row_id: history_to_delete[i] },
|
data: { row_id: history_to_delete[i] },
|
||||||
async: true,
|
async: true,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
var msg = "User history purged";
|
var msg = "History deleted";
|
||||||
showMsg(msg, false, true, 2000);
|
showMsg(msg, false, true, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -113,7 +113,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.delete-control').each(function () {
|
$('.delete-control').each(function () {
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
$('#row-edit-mode-alert').fadeOut(200);
|
$('#row-edit-mode-alert').fadeOut(200);
|
||||||
});
|
});
|
||||||
|
@ -121,6 +120,7 @@
|
||||||
} else {
|
} else {
|
||||||
history_to_delete = [];
|
history_to_delete = [];
|
||||||
$('.delete-control').each(function() {
|
$('.delete-control').each(function() {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
$(this).removeClass('hidden');
|
$(this).removeClass('hidden');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
<div class="modal-footer"></div>
|
<div class="modal-footer"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
|
||||||
|
</div>
|
||||||
<script src="interfaces/default/js/tables/history_table_modal.js"></script>
|
<script src="interfaces/default/js/tables/history_table_modal.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
@ -45,6 +46,32 @@
|
||||||
history_table = $('#history_table').DataTable(history_table_modal_options);
|
history_table = $('#history_table').DataTable(history_table_modal_options);
|
||||||
|
|
||||||
clearSearchButton('history_table', history_table);
|
clearSearchButton('history_table', history_table);
|
||||||
|
|
||||||
|
// Move #info-modal to parent container
|
||||||
|
if (!($('#history-modal').next().is('#info-modal'))) {
|
||||||
|
$('#info-modal').appendTo($('#history-modal').parent());
|
||||||
|
}
|
||||||
|
$('#history-modal > #info-modal').remove();
|
||||||
|
|
||||||
|
$('#history-modal').css('z-index', '1050');
|
||||||
|
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1049');
|
||||||
|
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
|
||||||
|
|
||||||
|
$('#info-modal').on('show.bs.modal', function () {
|
||||||
|
// Fix position to match parent modal
|
||||||
|
var currentPadding = parseInt($('body').css('padding-right'));
|
||||||
|
$(this).children('.modal-dialog').css('left', -currentPadding / 2);
|
||||||
|
$('#history-modal').css('overflow-y', 'hidden');
|
||||||
|
setTimeout(function () {
|
||||||
|
$('#info-modal').css('z-index', '1060');
|
||||||
|
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1059');
|
||||||
|
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
$('#info-modal').on('hidden.bs.modal', function () {
|
||||||
|
$('body').addClass('modal-open');
|
||||||
|
$('#history-modal').css('overflow-y', 'auto');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% else:
|
% else:
|
||||||
|
|
|
@ -17,6 +17,9 @@ data[array_index]['rows'] :: Usable parameters
|
||||||
|
|
||||||
row_id Return the db row id for a metadata item if one exists
|
row_id Return the db row id for a metadata item if one exists
|
||||||
|
|
||||||
|
== Only if 'stat_id' is 'top_tv' or 'popular_tv' or 'top_movies' or 'popular_movies' or 'last_watched' ==
|
||||||
|
thumb Return the thumb for the media item.
|
||||||
|
|
||||||
== Only if 'stat_id' is 'top_tv' or 'popular_tv' ==
|
== Only if 'stat_id' is 'top_tv' or 'popular_tv' ==
|
||||||
grandparent_thumb Returns location of the item's thumbnail. Use with pms_image_proxy.
|
grandparent_thumb Returns location of the item's thumbnail. Use with pms_image_proxy.
|
||||||
rating_key Returns the unique identifier for the media item.
|
rating_key Returns the unique identifier for the media item.
|
||||||
|
@ -29,15 +32,18 @@ total_duration Returns the total duration for the associated stat.
|
||||||
== Only of 'stat_id' is 'popular_tv' or 'popular_movies' ==
|
== Only of 'stat_id' is 'popular_tv' or 'popular_movies' ==
|
||||||
users_watched Returns the count for the associated stat.
|
users_watched Returns the count for the associated stat.
|
||||||
|
|
||||||
== Only if 'stat_id' is 'top_user' ==
|
== Only if 'stat_id' is 'top_user' or 'last_watched' ==
|
||||||
thumb Returns url of the user's gravatar. Returns '' if none exists.
|
user_thumb Returns url of the user's gravatar. Returns '' if none exists.
|
||||||
user Returns the username for the associated stat.
|
user Returns the username for the associated stat.
|
||||||
user_id Returns the user id for the associated stat.
|
user_id Returns the user id for the associated stat.
|
||||||
friendly_name Returns the friendly name of the user for the associated stat.
|
friendly_name Returns the friendly name of the user for the associated stat.
|
||||||
|
|
||||||
== Only if 'stat_id' is 'top_platform' ==
|
== Only if 'stat_id' is 'top_platform' or 'last_watched' ==
|
||||||
platform_type Returns the platform name for the associated stat.
|
platform_type Returns the platform name for the associated stat.
|
||||||
|
|
||||||
|
== Only if 'stat_id' is 'last_watched' ==
|
||||||
|
last_watch Returns the time the media item was last watched.
|
||||||
|
|
||||||
DOCUMENTATION :: END
|
DOCUMENTATION :: END
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
|
@ -48,7 +54,7 @@ DOCUMENTATION :: END
|
||||||
def hd(minutes):
|
def hd(minutes):
|
||||||
if int(minutes) > 60:
|
if int(minutes) > 60:
|
||||||
hours = int(helpers.cast_to_float(minutes) / 60)
|
hours = int(helpers.cast_to_float(minutes) / 60)
|
||||||
minutes = int(helpers.cast_to_float(minutes) % hours)
|
minutes = int(helpers.cast_to_float(minutes) % 60 )
|
||||||
if minutes > 0:
|
if minutes > 0:
|
||||||
return "<h3>" + str(hours) + "</h3><p>hrs</p><h3>" + str(minutes) + "</h3><p>mins</p>"
|
return "<h3>" + str(hours) + "</h3><p>hrs</p><h3>" + str(minutes) + "</h3><p>mins</p>"
|
||||||
else:
|
else:
|
||||||
|
@ -58,199 +64,587 @@ DOCUMENTATION :: END
|
||||||
%>
|
%>
|
||||||
|
|
||||||
% if data:
|
% if data:
|
||||||
% if data[0]['rows'] or data[2]['rows']:
|
% if data[0]['rows'] or data[1]['rows'] or data[2]['rows'] or data[3]['rows'] or data[4]['rows'] or data[5]['rows']:
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
% for a in data:
|
% for top_stat in data:
|
||||||
% if a['stat_id'] == 'top_tv' and a['rows']:
|
% if top_stat['stat_id'] == 'top_tv' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Watched TV</h4>
|
<h4>Most Watched TV</h4>
|
||||||
<h5><a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<h5>
|
||||||
${a['rows'][0]['title']}
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
</a></h5>
|
${top_stat['rows'][0]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
% if a['stat_type'] == 'total_plays':
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
<h3>${a['rows'][0]['total_plays']}</h3>
|
<h3>${top_stat['rows'][0]['total_plays']}</h3>
|
||||||
<p> plays</p>
|
<p> plays</p>
|
||||||
% else:
|
% else:
|
||||||
${a['rows'][0]['total_duration'] | hd}
|
${top_stat['rows'][0]['total_duration'] | hd}
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
% if a['rows'][0]['grandparent_thumb']:
|
% if top_stat['rows'][0]['grandparent_thumb']:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
${top_stat['rows'][loop.index]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
|
<h3>${top_stat['rows'][loop.index]['total_plays']}</h3>
|
||||||
|
<p> plays</p>
|
||||||
|
% else:
|
||||||
|
${top_stat['rows'][loop.index]['total_duration'] | hd}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
% if top_stat['rows'][loop.index]['grandparent_thumb']:
|
||||||
|
<div class="home-platforms-instance-list-poster">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster2">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
% elif a['stat_id'] == 'popular_tv' and a['rows']:
|
% elif top_stat['stat_id'] == 'popular_tv' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Popular TV</h4>
|
<h4>Most Popular TV</h4>
|
||||||
<h5><a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<h5>
|
||||||
${a['rows'][0]['title']}
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
</a></h5>
|
${top_stat['rows'][0]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
<h3>${a['rows'][0]['users_watched']}</h3>
|
<h3>${top_stat['rows'][0]['users_watched']}</h3>
|
||||||
<p> users</p>
|
<p> users</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
% if a['rows'][0]['grandparent_thumb'] != '':
|
% if top_stat['rows'][0]['grandparent_thumb'] != '':
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
${top_stat['rows'][loop.index]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
<h3>${top_stat['rows'][loop.index]['users_watched']}</h3>
|
||||||
|
<p> users</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
% if top_stat['rows'][loop.index]['grandparent_thumb']:
|
||||||
|
<div class="home-platforms-instance-list-poster">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster2">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
% elif a['stat_id'] == 'top_movies' and a['rows']:
|
% elif top_stat['stat_id'] == 'top_movies' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Watched Movie</h4>
|
<h4>Most Watched Movie</h4>
|
||||||
<h5><a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<h5>
|
||||||
${a['rows'][0]['title']}
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
</a></h5>
|
${top_stat['rows'][0]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
% if a['stat_type'] == 'total_plays':
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
<h3>${a['rows'][0]['total_plays']}</h3>
|
<h3>${top_stat['rows'][0]['total_plays']}</h3>
|
||||||
<p> plays</p>
|
<p> plays</p>
|
||||||
% else:
|
% else:
|
||||||
${a['rows'][0]['total_duration'] | hd}
|
${top_stat['rows'][0]['total_duration'] | hd}
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
% if a['rows'][0]['thumb']:
|
% if top_stat['rows'][0]['thumb']:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
${top_stat['rows'][loop.index]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
|
<h3>${top_stat['rows'][loop.index]['total_plays']}</h3>
|
||||||
|
<p> plays</p>
|
||||||
|
% else:
|
||||||
|
${top_stat['rows'][loop.index]['total_duration'] | hd}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
% if top_stat['rows'][loop.index]['thumb']:
|
||||||
|
<div class="home-platforms-instance-list-poster">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster2">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
% elif a['stat_id'] == 'popular_movies' and a['rows']:
|
% elif top_stat['stat_id'] == 'popular_movies' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Popular Movie</h4>
|
<h4>Most Popular Movie</h4>
|
||||||
<h5><a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<h5>
|
||||||
${a['rows'][0]['title']}
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
</a></h5>
|
${top_stat['rows'][0]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
<h3>${a['rows'][0]['users_watched']}</h3>
|
<h3>${top_stat['rows'][0]['users_watched']}</h3>
|
||||||
<p> users</p>
|
<p> users</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="info?item_id=${a['rows'][0]['rating_key']}">
|
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
|
||||||
% if a['rows'][0]['thumb']:
|
% if top_stat['rows'][0]['thumb']:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
${top_stat['rows'][loop.index]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
<h3>${top_stat['rows'][loop.index]['users_watched']}</h3>
|
||||||
|
<p> users</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}">
|
||||||
|
% if top_stat['rows'][loop.index]['thumb']:
|
||||||
|
<div class="home-platforms-instance-list-poster">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster2">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
% elif a['stat_id'] == 'top_users' and a['rows']:
|
% elif top_stat['stat_id'] == 'top_users' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Active User</h4>
|
<h4>Most Active User</h4>
|
||||||
<h5>
|
<h5>
|
||||||
% if a['rows'][0]['user_id']:
|
% if top_stat['rows'][0]['user_id']:
|
||||||
<a href="user?user_id=${a['rows'][0]['user_id']}">
|
<a href="user?user_id=${top_stat['rows'][0]['user_id']}">
|
||||||
% else:
|
% else:
|
||||||
<a href="user?user=${a['rows'][0]['user']}">
|
<a href="user?user=${top_stat['rows'][0]['user']}">
|
||||||
% endif
|
% endif
|
||||||
${a['rows'][0]['friendly_name']}
|
${top_stat['rows'][0]['friendly_name']}
|
||||||
</a>
|
</a>
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
% if a['stat_type'] == 'total_plays':
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
<h3>${a['rows'][0]['total_plays']}</h3>
|
<h3>${top_stat['rows'][0]['total_plays']}</h3>
|
||||||
<p> plays</p>
|
<p> plays</p>
|
||||||
% else:
|
% else:
|
||||||
${a['rows'][0]['total_duration'] | hd}
|
${top_stat['rows'][0]['total_duration'] | hd}
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% if a['rows'][0]['user_id']:
|
% if top_stat['rows'][0]['user_id']:
|
||||||
<a href="user?user_id=${a['rows'][0]['user_id']}">
|
<a href="user?user_id=${top_stat['rows'][0]['user_id']}">
|
||||||
% else:
|
% else:
|
||||||
<a href="user?user=${a['rows'][0]['user']}">
|
<a href="user?user=${top_stat['rows'][0]['user']}">
|
||||||
% endif
|
% endif
|
||||||
% if a['rows'][0]['thumb'] != '':
|
% if top_stat['rows'][0]['user_thumb'] != '':
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-oval" style="background-image: url(${a['rows'][0]['thumb']});">
|
<div class="home-platforms-instance-oval" style="background-image: url(${top_stat['rows'][0]['user_thumb']});"></div>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-oval" style="background-image: url(interfaces/default/images/gravatar-default.png);">
|
<div class="home-platforms-instance-oval" style="background-image: url(interfaces/default/images/gravatar-default.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
% if top_stat['rows'][loop.index]['user_id']:
|
||||||
|
<a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}">
|
||||||
|
% else:
|
||||||
|
<a href="user?user=${top_stat['rows'][loop.index]['user']}">
|
||||||
|
% endif
|
||||||
|
${top_stat['rows'][loop.index]['friendly_name']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
|
<h3>${top_stat['rows'][loop.index]['total_plays']}</h3>
|
||||||
|
<p> plays</p>
|
||||||
|
% else:
|
||||||
|
${top_stat['rows'][loop.index]['total_duration'] | hd}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% if top_stat['rows'][loop.index]['user_id']:
|
||||||
|
<a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}">
|
||||||
|
% else:
|
||||||
|
<a href="user?user=${top_stat['rows'][loop.index]['user']}">
|
||||||
|
% endif
|
||||||
|
% if top_stat['rows'][loop.index]['user_thumb'] != '':
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-instance-list-oval" style="background-image: url(${top_stat['rows'][loop.index]['user_thumb']});"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-instance-list-oval" style="background-image: url(interfaces/default/images/gravatar-default.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
% elif a['stat_id'] == 'top_platforms' and a['rows']:
|
% elif top_stat['stat_id'] == 'top_platforms' and top_stat['rows']:
|
||||||
<div class="home-platforms-instance">
|
<div class="home-platforms-instance">
|
||||||
<li>
|
<li>
|
||||||
<div class="home-platforms-instance-info">
|
<div class="home-platforms-instance-info">
|
||||||
<div class="home-platforms-instance-name">
|
<div class="home-platforms-instance-name">
|
||||||
<h4>Most Active Platform</h4>
|
<h4>Most Active Platform</h4>
|
||||||
<h5>${a['rows'][0]['platform_type']}</h5>
|
<h5>${top_stat['rows'][0]['platform_type']}</h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-platforms-instance-playcount">
|
<div class="home-platforms-instance-playcount">
|
||||||
% if a['stat_type'] == 'total_plays':
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
<h3>${a['rows'][0]['total_plays']}</h3>
|
<h3>${top_stat['rows'][0]['total_plays']}</h3>
|
||||||
<p> plays</p>
|
<p> plays</p>
|
||||||
% else:
|
% else:
|
||||||
${a['rows'][0]['total_duration'] | hd}
|
${top_stat['rows'][0]['total_duration'] | hd}
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="platform-stat" class="home-platforms-instance-poster">
|
<div id="platform-stat" class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-box" style="background-image: url(interfaces/default/images/platforms/default.png);">
|
<script>
|
||||||
|
$("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][0]['platform_type']}') + ");'>");
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
${top_stat['rows'][loop.index]['platform_type']}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-playcount">
|
||||||
|
% if top_stat['stat_type'] == 'total_plays':
|
||||||
|
<h3>${top_stat['rows'][loop.index]['total_plays']}</h3>
|
||||||
|
<p> plays</p>
|
||||||
|
% else:
|
||||||
|
${top_stat['rows'][loop.index]['total_duration'] | hd}
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-poster" id="home-platforms-instance-poster-${loop.index + 1}">
|
||||||
|
<script>
|
||||||
|
$("#home-platforms-instance-poster-${loop.index + 1}").html("<div class='home-platforms-instance-list-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][loop.index]['platform_type']}') + ");'>");
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
% elif top_stat['stat_id'] == 'last_watched' and top_stat['rows']:
|
||||||
|
<div class="home-platforms-instance">
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-info">
|
||||||
|
<div class="home-platforms-instance-name">
|
||||||
|
<h4>Last Watched</h4>
|
||||||
|
<h5>
|
||||||
|
<a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}">
|
||||||
|
${top_stat['rows'][0]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-last-user">
|
||||||
|
<h5>
|
||||||
|
% if top_stat['rows'][0]['user_id']:
|
||||||
|
<a href="user?user_id=${top_stat['rows'][0]['user_id']}">
|
||||||
|
% else:
|
||||||
|
<a href="user?user=${top_stat['rows'][0]['user']}">
|
||||||
|
% endif
|
||||||
|
${top_stat['rows'][0]['friendly_name']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
<p>
|
||||||
|
<span id="last-watch-stat">
|
||||||
|
<script>
|
||||||
|
$('#last-watch-stat').text(moment(${top_stat['rows'][0]['last_watch']},"X").format(date_format));
|
||||||
|
</script>
|
||||||
|
</span> - ${top_stat['rows'][0]['platform_type']}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}">
|
||||||
|
% if top_stat['rows'][0]['thumb']:
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
%if len(top_stat['rows']) > 1:
|
||||||
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<div class="slider">
|
||||||
|
<div class="home-platforms-instance-list">
|
||||||
|
% for row in top_stat['rows']:
|
||||||
|
%if loop.index > 0:
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-list-info">
|
||||||
|
<div class="home-platforms-instance-list-name">
|
||||||
|
<h5>
|
||||||
|
<a href="info?source=history&item_id=${top_stat['rows'][loop.index]['row_id']}">
|
||||||
|
${top_stat['rows'][loop.index]['title']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-list-last-user">
|
||||||
|
<h5>
|
||||||
|
% if top_stat['rows'][loop.index]['user_id']:
|
||||||
|
<a href="user?user_id=${top_stat['rows'][loop.index]['user_id']}">
|
||||||
|
% else:
|
||||||
|
<a href="user?user=${top_stat['rows'][loop.index]['user']}">
|
||||||
|
% endif
|
||||||
|
${top_stat['rows'][loop.index]['friendly_name']}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
<p>
|
||||||
|
<span id="home-platforms-instance-list-last-watch-${loop.index + 1}">
|
||||||
|
<script>
|
||||||
|
$('#home-platforms-instance-list-last-watch-${loop.index + 1}').text(moment(${top_stat['rows'][loop.index]['last_watch']},"X").format(date_format));
|
||||||
|
</script>
|
||||||
|
</span> - ${top_stat['rows'][loop.index]['platform_type']}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="info?source=history&item_id=${top_stat['rows'][loop.index]['row_id']}">
|
||||||
|
% if top_stat['rows'][loop.index]['thumb']:
|
||||||
|
<div class="home-platforms-instance-list-poster">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster2">
|
||||||
|
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</a>
|
||||||
|
<div class="home-platforms-instance-list-number">
|
||||||
|
<h4>${loop.index + 1}</h4>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
% endif
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
|
||||||
$("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath('${a['rows'][0]['platform_type']}') + ");'>");
|
|
||||||
</script>
|
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
</ul>
|
</ul>
|
||||||
|
<script>
|
||||||
|
var topZIndex = 2;
|
||||||
|
$('.home-platforms-instance-list-chevron').on('click', function() {
|
||||||
|
var instanceBoxChevron = $(this);
|
||||||
|
var instanceBox = $(this).parents('.home-platforms-instance');
|
||||||
|
var instanceBoxSlider = instanceBox.find('.slider');
|
||||||
|
|
||||||
|
topZIndex++;
|
||||||
|
instanceBoxChevron.toggleClass('active');
|
||||||
|
instanceBoxSlider.css('z-index', topZIndex);
|
||||||
|
instanceBoxSlider.stop().slideToggle(500);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">No stats for selected period.</div><br>
|
<div class="text-muted">No stats for selected period.</div><br>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="padded-header">
|
<div class="padded-header">
|
||||||
<h3>Statistics <small>Last ${config['home_stats_length']} days</small></h3>
|
<h3>Watch Statistics <small>Last ${config['home_stats_length']} days</small></h3>
|
||||||
</div>
|
</div>
|
||||||
<div id="home-stats" class="home-platforms">
|
<div id="home-stats" class="home-platforms">
|
||||||
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
|
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
|
||||||
|
@ -27,6 +27,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="padded-header" id="library-statistics-header">
|
||||||
|
<h3>Library Statistics</h3>
|
||||||
|
</div>
|
||||||
|
<div id="library-stats" class="library-platforms">
|
||||||
|
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class='row'>
|
<div class='row'>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="padded-header">
|
<div class="padded-header">
|
||||||
|
@ -45,17 +56,18 @@
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function getHomeStats(days, plays) {
|
function currentActivityHeader() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'home_stats',
|
url: 'get_current_activity_header',
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
data: {time_range: days, stat_type: plays},
|
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#home-stats").html(xhr.responseText);
|
$("#current-activity-header").html(xhr.responseText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
currentActivityHeader();
|
||||||
|
setInterval(currentActivityHeader, 15000);
|
||||||
|
|
||||||
function currentActivity() {
|
function currentActivity() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -70,18 +82,50 @@
|
||||||
currentActivity();
|
currentActivity();
|
||||||
setInterval(currentActivity, 15000);
|
setInterval(currentActivity, 15000);
|
||||||
|
|
||||||
function currentActivityHeader() {
|
function getHomeStats(days, stat_type, stat_count) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_current_activity_header',
|
url: 'home_stats',
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
|
data: {time_range: days, stat_type: stat_type, stat_count: stat_count},
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#current-activity-header").html(xhr.responseText);
|
$("#home-stats").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLibraryStatsHeader() {
|
||||||
|
$.ajax({
|
||||||
|
"url": "get_servers_info",
|
||||||
|
type: "post",
|
||||||
|
cache: false,
|
||||||
|
async: true,
|
||||||
|
data: { },
|
||||||
|
complete: function (xhr, status) {
|
||||||
|
server_info = $.parseJSON(xhr.responseText);
|
||||||
|
var server_name = 'Server name not found';
|
||||||
|
for (var i in server_info) {
|
||||||
|
if (server_info[i].machine_identifier == '${config['pms_identifier']}') {
|
||||||
|
server_name = server_info[i].name
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#library-statistics-header h3').append(' <small>' + server_name + '</small>')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLibraryStats() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'library_stats',
|
||||||
|
cache: false,
|
||||||
|
async: true,
|
||||||
|
data: { },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#library-stats").html(xhr.responseText);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
currentActivityHeader();
|
|
||||||
setInterval(currentActivityHeader, 15000);
|
|
||||||
|
|
||||||
function recentlyAdded() {
|
function recentlyAdded() {
|
||||||
var widthVal = $('body').find(".container-fluid").width();
|
var widthVal = $('body').find(".container-fluid").width();
|
||||||
|
@ -110,7 +154,20 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
getHomeStats(${config['home_stats_length']}, ${config['home_stats_type']});
|
var date_format = 'YYYY-MM-DD';
|
||||||
|
var time_format = 'hh:mm a';
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_date_formats',
|
||||||
|
type: 'GET',
|
||||||
|
success: function(data) {
|
||||||
|
date_format = data.date_format;
|
||||||
|
time_format = data.time_format;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getHomeStats(${config['home_stats_length']}, ${config['home_stats_type']}, ${config['home_stats_count']});
|
||||||
|
getLibraryStatsHeader();
|
||||||
|
getLibraryStats();
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -47,201 +47,220 @@ DOCUMENTATION :: END
|
||||||
% if data:
|
% if data:
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div>
|
<div class="art-face" style="background-image:url(pms_image_proxy?img=${data['art']}&width=1920&height=1080)"></div>
|
||||||
<div class="art-face" style="background-image:url(pms_image_proxy?img=${data['art']}&width=1920&height=1080)">
|
<div class="summary-container">
|
||||||
<div class="summary-wrapper">
|
<div class="summary-navbar">
|
||||||
<div class="summary-overlay">
|
<div class="col-md-12">
|
||||||
<div class="row">
|
<div class="summary-navbar-list">
|
||||||
<div class="col-md-9">
|
% if data['type'] == 'movie':
|
||||||
<div class="summary-content-poster hidden-xs hidden-sm">
|
<span>Movies</span>
|
||||||
% if data['type'] == 'episode' and data['parent_thumb']:
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${data['parent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
<span><a href="#">${data['title']}</a></span>
|
||||||
% elif data['type'] == 'episode':
|
% elif data['type'] == 'show':
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${data['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
|
<span>TV Shows</span>
|
||||||
% else:
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div>
|
<span><a href="#">${data['title']}</a></span>
|
||||||
% endif
|
% elif data['type'] == 'season':
|
||||||
</div>
|
<span>TV Shows</span>
|
||||||
<div class="summary-content">
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
<div class="summary-content-title">
|
<span><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></span>
|
||||||
% if data['type'] == 'movie':
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
<h1>${data['title']}</h1>
|
<span><a href="#">Season ${data['index']}</a></span>
|
||||||
% elif data['type'] == 'season':
|
% elif data['type'] == 'episode':
|
||||||
<h1>${data['parent_title']} (${data['title']})</h1>
|
<span>TV Shows</span>
|
||||||
% elif data['type'] == 'episode':
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
<h1>${data['grandparent_title']} - ${data['title']}
|
<span><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></span>
|
||||||
(Season ${data['parent_index']}, Episode ${data['index']})</h1>
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
% else:
|
<span><a href="info?item_id=${data['parent_rating_key']}">Season ${data['parent_index']}</a></span>
|
||||||
<h1>${data['title']}</h1>
|
<span><i class="fa fa-chevron-right"></i></span>
|
||||||
% endif
|
<span><a href="#">Episode ${data['index']} - ${data['title']}</a></span>
|
||||||
</div>
|
% endif
|
||||||
% if (data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode') and data['rating']:
|
|
||||||
<div id="stars" class="rateit hidden-xs hidden-sm" data-rateit-value=""
|
|
||||||
data-rateit-ispreset="true" data-rateit-readonly="true"></div>
|
|
||||||
% endif
|
|
||||||
<div class="summary-content-details-wrapper">
|
|
||||||
<div class="summary-content-director">
|
|
||||||
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['directors']:
|
|
||||||
Directed by <strong> ${data['directors'][0]}</strong>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
<div class="summary-content-studio">
|
|
||||||
% if (data['type'] == 'show' or data['type'] == 'movie') and data['studio']:
|
|
||||||
Studio <strong> ${data['studio']}</strong>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
<div class="summary-content-airdate">
|
|
||||||
% if data['type'] == 'movie':
|
|
||||||
Year <strong> ${data['year']}</strong>
|
|
||||||
% elif data['type'] == 'show':
|
|
||||||
Aired <strong> ${data['year']}</strong>
|
|
||||||
% elif data['type'] == 'episode':
|
|
||||||
Aired <strong> <span id="airdate">${data['originally_available_at']}</span></strong>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
<div class="summary-content-duration">
|
|
||||||
Runtime <strong> <span id="runtime">${data['duration']}</span> mins</strong>
|
|
||||||
</div>
|
|
||||||
<div class="summary-content-content-rating">
|
|
||||||
% if (data['type'] == 'episode' or data['type'] == 'movie' or data['type'] == 'show') and data['content_rating']:
|
|
||||||
Rated <strong> ${data['content_rating']} </strong>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="summary-content-summary">
|
|
||||||
<p> ${data['summary']} </p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="summary-content-people-wrapper hidden-xs hidden-sm">
|
|
||||||
% if (data['type'] == 'movie' or data['type'] == 'show') and data['genres']:
|
|
||||||
<div class="summary-content-genres">
|
|
||||||
<strong>Genres</strong>
|
|
||||||
<ul>
|
|
||||||
% for genre in data['genres']:
|
|
||||||
% if loop.index < 5:
|
|
||||||
<li>
|
|
||||||
${genre}
|
|
||||||
</li>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['writers']:
|
|
||||||
<div class="summary-content-writers">
|
|
||||||
<strong>Written by</strong>
|
|
||||||
<ul>
|
|
||||||
% for writer in data['writers']:
|
|
||||||
% if loop.index < 5:
|
|
||||||
<li>
|
|
||||||
${writer}
|
|
||||||
</li>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% if (data['type'] == 'movie' or data['type'] == 'show') and data['actors']:
|
|
||||||
<div class="summary-content-actors">
|
|
||||||
<strong>Starring</strong>
|
|
||||||
<ul>
|
|
||||||
% for actor in data['actors']:
|
|
||||||
% if loop.index < 5:
|
|
||||||
<li>
|
|
||||||
${actor}
|
|
||||||
</li>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="summary-content-title-wrapper">
|
||||||
</div>
|
<div class="col-md-9">
|
||||||
</div>
|
<div class="summary-content-poster hidden-xs hidden-sm">
|
||||||
% if data['type'] == 'movie' or data['type'] == 'episode' or data['type'] == 'show':
|
% if data['type'] == 'episode':
|
||||||
<div class='container-fluid'>
|
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);"></div>
|
||||||
<div class='row'>
|
% elif data['type'] == 'season':
|
||||||
<div class='col-md-12'>
|
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
<div class='table-card-header'>
|
% else:
|
||||||
<div class="header-bar">
|
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div>
|
||||||
<span>Watch History for <strong>${data['title']}</strong></span>
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="summary-content-title">
|
||||||
<span data-toggle="popover" data-placement="left" data-content="Select rows to delete. Data is deleted upon exiting delete mode." id="delete-message">
|
% if data['type'] == 'movie' or data['type'] == 'show':
|
||||||
<button class="btn btn-danger" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
<h1> </h1><h1>${data['title']}</h1>
|
||||||
<i class="fa fa-trash-o"></i> Delete mode
|
% elif data['type'] == 'season':
|
||||||
</button> 
|
<h1> </h1><h1><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></h1>
|
||||||
</span>
|
<h3 class="hidden-xs">S${data['index']}</h3>
|
||||||
<div class="colvis-button-bar hidden-xs"></div>
|
% elif data['type'] == 'episode':
|
||||||
</div>
|
<h1><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></h1>
|
||||||
</div>
|
<h2>${data['title']}</h2>
|
||||||
<div class="table-card-back">
|
<h3 class="hidden-xs">S${data['parent_index']} · E${data['index']}</h3>
|
||||||
<table class="display" id="history_table" width="100%">
|
% endif
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th align='left' id="delete">Delete</th>
|
|
||||||
<th align='left' id="time">Time</th>
|
|
||||||
<th align='left' id="friendly_name">User</th>
|
|
||||||
<th align='left' id="ip_address">IP Address</th>
|
|
||||||
<th align='left' id="platform">Platform</th>
|
|
||||||
<th align='left' id="title">Title</th>
|
|
||||||
<th align='left' id="started">Started</th>
|
|
||||||
<th align='left' id="paused_counter">Paused</th>
|
|
||||||
<th align='left' id="stopped">Stopped</th>
|
|
||||||
<th align='left' id="duration">Duration</th>
|
|
||||||
<th align='left' id="percent_complete"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div id="info-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="info-modal">
|
|
||||||
</div>
|
|
||||||
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
|
|
||||||
</div>
|
|
||||||
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
|
||||||
<h4 class="modal-title" id="myModalLabel">Confirm Delete</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body" style="text-align: center;">
|
|
||||||
<p>Are you REALLY sure you want to delete <strong><span id="deleteCount"></span></strong> history item(s)?</p>
|
|
||||||
<p>This is permanent and cannot be undone!</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
|
|
||||||
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-delete">Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="summary-content-wrapper">
|
||||||
</div>
|
<div class="col-md-9">
|
||||||
</div>
|
% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'season':
|
||||||
% elif data['type'] == 'season':
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 275px;"></div>
|
||||||
<div class='container-fluid'>
|
% else:
|
||||||
<div class='row'>
|
<div class="summary-content-padding hidden-xs hidden-sm"></div>
|
||||||
<div class='col-md-12'>
|
% endif
|
||||||
<div class='table-card-header'>
|
<div class="summary-content">
|
||||||
<div class="header-bar">
|
<div class="summary-content-details-wrapper">
|
||||||
<span>Episode List for <strong>${data['title']}</strong></span>
|
% if (data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode') and data['rating']:
|
||||||
|
<div id="stars" class="rateit hidden-xs hidden-sm" data-rateit-value=""
|
||||||
|
data-rateit-ispreset="true" data-rateit-readonly="true"></div>
|
||||||
|
% endif
|
||||||
|
<div class="summary-content-director">
|
||||||
|
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['directors']:
|
||||||
|
Directed by <strong> ${data['directors'][0]}</strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-studio">
|
||||||
|
% if (data['type'] == 'show' or data['type'] == 'movie') and data['studio']:
|
||||||
|
Studio <strong> ${data['studio']}</strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-airdate">
|
||||||
|
% if data['type'] == 'movie':
|
||||||
|
Year <strong> ${data['year']}</strong>
|
||||||
|
% elif data['type'] == 'show':
|
||||||
|
Aired <strong> ${data['year']}</strong>
|
||||||
|
% elif data['type'] == 'episode':
|
||||||
|
Aired <strong> <span id="airdate">${data['originally_available_at']}</span></strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-duration">
|
||||||
|
Runtime <strong> <span id="runtime">${data['duration']}</span> mins</strong>
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-content-rating">
|
||||||
|
% if (data['type'] == 'episode' or data['type'] == 'movie' or data['type'] == 'show') and data['content_rating']:
|
||||||
|
Rated <strong> ${data['content_rating']} </strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-summary">
|
||||||
|
<p> ${data['summary']} </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="summary-content-people-wrapper hidden-xs hidden-sm">
|
||||||
|
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['writers']:
|
||||||
|
<div class="summary-content-writers">
|
||||||
|
<strong>Written by</strong>
|
||||||
|
<ul>
|
||||||
|
% for writer in data['writers']:
|
||||||
|
% if loop.index < 5:
|
||||||
|
<li>
|
||||||
|
${writer}
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% if (data['type'] == 'movie' or data['type'] == 'show') and data['actors']:
|
||||||
|
<div class="summary-content-actors">
|
||||||
|
<strong>Starring</strong>
|
||||||
|
<ul>
|
||||||
|
% for actor in data['actors']:
|
||||||
|
% if loop.index < 5:
|
||||||
|
<li>
|
||||||
|
${actor}
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-people-wrapper hidden-xs hidden-sm">
|
||||||
|
% if (data['type'] == 'movie' or data['type'] == 'show') and data['genres']:
|
||||||
|
<div class="summary-content-genres">
|
||||||
|
<strong>Genres</strong>
|
||||||
|
<ul>
|
||||||
|
% for genre in data['genres']:
|
||||||
|
% if loop.index < 5:
|
||||||
|
<li>
|
||||||
|
${genre}
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% if data['type'] == 'show':
|
||||||
|
<div class='col-md-12'>
|
||||||
|
<div class='table-card-header'>
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>Season List for <strong>${data['title']}</strong></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='table-card-back'>
|
||||||
|
<div id="season-list"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% elif data['type'] == 'season':
|
||||||
|
<div class='col-md-12'>
|
||||||
|
<div class='table-card-header'>
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>Episode List for <strong>${data['title']}</strong></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='table-card-back'>
|
||||||
|
<div id="episode-list"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% if data['type'] == 'movie' or data['type'] == 'episode' or data['type'] == 'show' or data['type'] == 'season':
|
||||||
|
<div class='col-md-12'>
|
||||||
|
<div class='table-card-header'>
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>Watch History for <strong>${data['title']}</strong></span>
|
||||||
|
</div>
|
||||||
|
<div class="button-bar">
|
||||||
|
<div class="colvis-button-bar hidden-xs"></div>
|
||||||
|
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
||||||
|
<i class="fa fa-trash-o"></i> Delete mode
|
||||||
|
</button>
|
||||||
|
<div class="alert alert-danger alert-edit" role="alert" id="row-edit-mode-alert"><i class="fa fa-exclamation-triangle"></i> Select rows to delete. Data is deleted upon exiting delete mode.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-card-back">
|
||||||
|
<table class="display" id="history_table" width="100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th align='left' id="delete">Delete</th>
|
||||||
|
<th align='left' id="time">Time</th>
|
||||||
|
<th align='left' id="friendly_name">User</th>
|
||||||
|
<th align='left' id="ip_address">IP Address</th>
|
||||||
|
<th align='left' id="platform">Platform</th>
|
||||||
|
<th align='left' id="title">Title</th>
|
||||||
|
<th align='left' id="started">Started</th>
|
||||||
|
<th align='left' id="paused_counter">Paused</th>
|
||||||
|
<th align='left' id="stopped">Stopped</th>
|
||||||
|
<th align='left' id="duration">Duration</th>
|
||||||
|
<th align='left' id="percent_complete"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="info-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="info-modal">
|
||||||
|
</div>
|
||||||
|
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
|
||||||
<div id="episode-list"></div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -249,8 +268,10 @@ DOCUMENTATION :: END
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<h3>Error retrieving item data. This media may not be available in the Plex Media Server database
|
<h3>
|
||||||
anymore.</h3>
|
Error retrieving item data. This media may not be available in the Plex Media Server database
|
||||||
|
anymore.
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -282,8 +303,7 @@ DOCUMENTATION :: END
|
||||||
type: 'post',
|
type: 'post',
|
||||||
data: function ( d ) {
|
data: function ( d ) {
|
||||||
return { 'json_data': JSON.stringify( d ),
|
return { 'json_data': JSON.stringify( d ),
|
||||||
'rating_key': ${data['rating_key']}
|
'rating_key': ${data['rating_key']} };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
history_table = $('#history_table').DataTable(history_table_options);
|
history_table = $('#history_table').DataTable(history_table_options);
|
||||||
|
@ -293,62 +313,6 @@ DOCUMENTATION :: END
|
||||||
|
|
||||||
clearSearchButton('history_table', history_table);
|
clearSearchButton('history_table', history_table);
|
||||||
|
|
||||||
$('#row-edit-mode').on('click', function() {
|
|
||||||
$('#delete-message').popover();
|
|
||||||
|
|
||||||
if ($(this).hasClass('active')) {
|
|
||||||
if (history_to_delete.length > 0) {
|
|
||||||
$('#deleteCount').text(history_to_delete.length);
|
|
||||||
$('#confirm-modal').modal();
|
|
||||||
$('#confirm-modal').one('click', '#confirm-delete', function () {
|
|
||||||
for (var i = 0; i < history_to_delete.length; i++) {
|
|
||||||
$.ajax({
|
|
||||||
url: 'delete_history_rows',
|
|
||||||
data: { row_id: history_to_delete[i] },
|
|
||||||
async: true,
|
|
||||||
success: function (data) {
|
|
||||||
var msg = "User history purged";
|
|
||||||
showMsg(msg, false, true, 2000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
history_table.draw();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.delete-control').each(function () {
|
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
|
||||||
$(this).addClass('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
history_to_delete = [];
|
|
||||||
$('.delete-control').each(function() {
|
|
||||||
$(this).removeClass('hidden');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% elif data['type'] == 'show':
|
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
history_table_options.ajax = {
|
|
||||||
"url": "get_history",
|
|
||||||
type: 'post',
|
|
||||||
data: function ( d ) {
|
|
||||||
return { 'json_data': JSON.stringify( d ),
|
|
||||||
'grandparent_rating_key': ${data['rating_key']}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
history_table = $('#history_table').DataTable(history_table_options);
|
|
||||||
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
|
|
||||||
$(colvis.button()).appendTo('div.colvis-button-bar');
|
|
||||||
|
|
||||||
clearSearchButton('history_table', history_table);
|
|
||||||
|
|
||||||
$('#row-edit-mode').click(function() {
|
$('#row-edit-mode').click(function() {
|
||||||
if ($(this).hasClass('active')) {
|
if ($(this).hasClass('active')) {
|
||||||
$('.delete-control').each(function() {
|
$('.delete-control').each(function() {
|
||||||
|
@ -362,24 +326,143 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% elif data['type'] == 'show':
|
||||||
|
<script src="interfaces/default/js/tables/history_table.js"></script>
|
||||||
% if data['type'] == 'season':
|
|
||||||
<script>
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
history_table_options.ajax = {
|
||||||
|
"url": "get_history",
|
||||||
|
type: 'post',
|
||||||
|
data: function ( d ) {
|
||||||
|
return { 'json_data': JSON.stringify( d ),
|
||||||
|
'grandparent_rating_key': ${data['rating_key']} };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
history_table = $('#history_table').DataTable(history_table_options);
|
||||||
|
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
|
||||||
|
$(colvis.button()).appendTo('div.colvis-button-bar');
|
||||||
|
|
||||||
|
clearSearchButton('history_table', history_table);
|
||||||
|
|
||||||
|
$('#row-edit-mode').on('click', function() {
|
||||||
|
$('#row-edit-mode-alert').fadeIn(200);
|
||||||
|
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
if (history_to_delete.length > 0) {
|
||||||
|
$('#deleteCount').text(history_to_delete.length);
|
||||||
|
$('#confirm-modal').modal();
|
||||||
|
$('#confirm-modal').one('click', '#confirm-delete', function () {
|
||||||
|
for (var i = 0; i < history_to_delete.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'delete_history_rows',
|
||||||
|
data: { row_id: history_to_delete[i] },
|
||||||
|
async: true,
|
||||||
|
success: function (data) {
|
||||||
|
var msg = "History deleted";
|
||||||
|
showMsg(msg, false, true, 2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
history_table.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.delete-control').each(function () {
|
||||||
|
$(this).addClass('hidden');
|
||||||
|
$('#row-edit-mode-alert').fadeOut(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
history_to_delete = [];
|
||||||
|
$('.delete-control').each(function() {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
$(this).removeClass('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_children',
|
url: 'get_show_children',
|
||||||
type: "GET",
|
type: "GET",
|
||||||
async: true,
|
async: true,
|
||||||
data: { rating_key : ${data['rating_key']} },
|
data: { rating_key : ${data['rating_key']} },
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#episode-list").html(xhr.responseText);
|
$("#season-list").html(xhr.responseText); }
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
% endif
|
||||||
|
% if data['type'] == 'season':
|
||||||
|
<script src="interfaces/default/js/tables/history_table.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
history_table_options.ajax = {
|
||||||
|
"url": "get_history",
|
||||||
|
type: 'post',
|
||||||
|
data: function ( d ) {
|
||||||
|
return { 'json_data': JSON.stringify( d ),
|
||||||
|
'parent_rating_key': ${data['rating_key']} };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
history_table = $('#history_table').DataTable(history_table_options);
|
||||||
|
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
|
||||||
|
$(colvis.button()).appendTo('div.colvis-button-bar');
|
||||||
|
|
||||||
|
clearSearchButton('history_table', history_table);
|
||||||
|
|
||||||
|
$('#row-edit-mode').on('click', function() {
|
||||||
|
$('#row-edit-mode-alert').fadeIn(200);
|
||||||
|
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
if (history_to_delete.length > 0) {
|
||||||
|
$('#deleteCount').text(history_to_delete.length);
|
||||||
|
$('#confirm-modal').modal();
|
||||||
|
$('#confirm-modal').one('click', '#confirm-delete', function () {
|
||||||
|
for (var i = 0; i < history_to_delete.length; i++) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'delete_history_rows',
|
||||||
|
data: { row_id: history_to_delete[i] },
|
||||||
|
async: true,
|
||||||
|
success: function (data) {
|
||||||
|
var msg = "History deleted";
|
||||||
|
showMsg(msg, false, true, 2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
history_table.draw();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.delete-control').each(function () {
|
||||||
|
$(this).addClass('hidden');
|
||||||
|
$('#row-edit-mode-alert').fadeOut(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
history_to_delete = [];
|
||||||
|
$('.delete-control').each(function() {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
$(this).removeClass('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_season_children',
|
||||||
|
type: "GET",
|
||||||
|
async: true,
|
||||||
|
data: { rating_key : ${data['rating_key']} },
|
||||||
|
complete: function(xhr, status) {
|
||||||
|
$("#episode-list").html(xhr.responseText); }
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
<script>
|
<script>
|
||||||
$("#airdate").html(moment($("#airdate")).format('MMM DD, YYYY'));
|
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
|
||||||
$("#runtime").html(millisecondsToMinutes($("#runtime").html(), true));
|
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
|
<script>
|
||||||
|
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
||||||
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
|
@ -34,7 +34,7 @@ DOCUMENTATION :: END
|
||||||
<div class="season-episodes-poster">
|
<div class="season-episodes-poster">
|
||||||
<div class="season-episodes-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);">
|
<div class="season-episodes-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);">
|
||||||
<div class="season-episodes-card-overlay">
|
<div class="season-episodes-card-overlay">
|
||||||
<div class="season-episodes-season">
|
<div class="season-episodes-overlay-text">
|
||||||
Episode ${a['index']}
|
Episode ${a['index']}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
55
data/interfaces/default/info_season_list.html
Normal file
55
data/interfaces/default/info_season_list.html
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<%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_season_list.html
|
||||||
|
Version: 0.1
|
||||||
|
Variable names: data [list]
|
||||||
|
|
||||||
|
data :: Usable parameters
|
||||||
|
|
||||||
|
== Global keys ==
|
||||||
|
season_count Returns the number of seasons in the array.
|
||||||
|
season_list Returns an array of seasons.
|
||||||
|
|
||||||
|
data['season_list'] :: Usable paramaters
|
||||||
|
|
||||||
|
== Global keys ==
|
||||||
|
rating_key Returns the unique identifier for the media item.
|
||||||
|
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||||
|
title Returns the name of the season.
|
||||||
|
index Returns the season number.
|
||||||
|
|
||||||
|
DOCUMENTATION :: END
|
||||||
|
</%doc>
|
||||||
|
|
||||||
|
% if data != None:
|
||||||
|
% if data['season_count'] > 0:
|
||||||
|
<div class="show-seasons-wrapper">
|
||||||
|
<ul class="show-seasons-instance list-unstyled">
|
||||||
|
% for a in data['season_list']:
|
||||||
|
% if a['rating_key']:
|
||||||
|
<li>
|
||||||
|
<a href="info?item_id=${a['rating_key']}">
|
||||||
|
<div class="show-seasons-poster">
|
||||||
|
% if a['thumb']:
|
||||||
|
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=450);">
|
||||||
|
% else:
|
||||||
|
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['parent_thumb']}&width=300&height=450);">
|
||||||
|
% endif
|
||||||
|
<div class="show-seasons-card-overlay">
|
||||||
|
<div class="show-seasons-overlay-text">
|
||||||
|
Season ${a['index']}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% endif
|
|
@ -74,6 +74,19 @@ history_table_modal_options = {
|
||||||
{
|
{
|
||||||
"targets": [3],
|
"targets": [3],
|
||||||
"data":"player",
|
"data":"player",
|
||||||
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
|
if (cellData !== '') {
|
||||||
|
var transcode_dec = '';
|
||||||
|
if (rowData['video_decision'] === 'transcode') {
|
||||||
|
transcode_dec = '<span class="transcode-tooltip" data-toggle="tooltip" title="Transcode"><i class="fa fa-server fa-fw"></i></span>';
|
||||||
|
} else if (rowData['video_decision'] === 'copy') {
|
||||||
|
transcode_dec = '<span class="transcode-tooltip" data-toggle="tooltip" title="Direct Stream"><i class="fa fa-video-camera fa-fw"></i></span>';
|
||||||
|
} else if (rowData['video_decision'] === 'direct play' || rowData['video_decision'] === '') {
|
||||||
|
transcode_dec = '<span class="transcode-tooltip" data-toggle="tooltip" title="Direct Play"><i class="fa fa-play-circle fa-fw"></i></span>';
|
||||||
|
}
|
||||||
|
$(td).html('<div><a href="#" data-target="#info-modal" data-toggle="modal"><div style="float: left;">' + transcode_dec + ' ' + cellData + '</div></a></div>');
|
||||||
|
}
|
||||||
|
},
|
||||||
"className": "no-wrap hidden-sm hidden-xs modal-control"
|
"className": "no-wrap hidden-sm hidden-xs modal-control"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -81,14 +94,21 @@ history_table_modal_options = {
|
||||||
"data":"full_title",
|
"data":"full_title",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== '') {
|
if (cellData !== '') {
|
||||||
if (rowData['media_type'] === 'movie' || rowData['media_type'] === 'episode') {
|
var media_type = '';
|
||||||
var transcode_dec = '';
|
var thumb_popover = '';
|
||||||
if (rowData['video_decision'] === 'transcode') {
|
if (rowData['media_type'] === 'movie') {
|
||||||
transcode_dec = '<i class="fa fa-server"></i> ';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Movie"><i class="fa fa-film fa-fw"></i></span>';
|
||||||
}
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120">' + cellData + ' (' + rowData['year'] + ')</span>'
|
||||||
$(td).html('<div><div style="float: left;"><a href="info?source=history&item_id=' + rowData['id'] + '">' + cellData + '</a></div><div style="float: right; text-align: right; padding-right: 5px;">' + transcode_dec + '<i class="fa fa-video-camera"></i></div></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120">' + cellData + ' \
|
||||||
|
(S' + ('00' + rowData['parent_media_index']).slice(-2) + 'E' + ('00' + rowData['media_index']).slice(-2) + ')</span>'
|
||||||
|
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else if (rowData['media_type'] === 'track') {
|
} else if (rowData['media_type'] === 'track') {
|
||||||
$(td).html('<div><div style="float: left;">' + cellData + '</div><div style="float: right; text-align: right; padding-right: 5px;"><i class="fa fa-music"></i></div></div>');
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
|
||||||
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=300&fallback=poster" data-height="80">' + cellData + ' (' + rowData['parent_title'] + ')</span>'
|
||||||
|
$(td).html('<div class="history-title"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></div>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
|
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
|
||||||
}
|
}
|
||||||
|
@ -100,9 +120,40 @@ history_table_modal_options = {
|
||||||
// Jump to top of page
|
// Jump to top of page
|
||||||
// $('html,body').scrollTop(0);
|
// $('html,body').scrollTop(0);
|
||||||
$('#ajaxMsg').fadeOut();
|
$('#ajaxMsg').fadeOut();
|
||||||
|
|
||||||
|
// Create the tooltips.
|
||||||
|
$('.transcode-tooltip').tooltip();
|
||||||
|
$('.media-type-tooltip').tooltip();
|
||||||
|
$('.thumb-tooltip').popover({
|
||||||
|
html: true,
|
||||||
|
trigger: 'hover',
|
||||||
|
placement: 'right',
|
||||||
|
content: function () {
|
||||||
|
return '<div class="history-thumbnail" style="background-image: url(' + $(this).data('img') + '); height: ' + $(this).data('height') + 'px;" />';
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
"preDrawCallback": function(settings) {
|
"preDrawCallback": function(settings) {
|
||||||
var msg = "<div class='msg'><i class='fa fa-refresh fa-spin'></i> Fetching rows...</div>";
|
var msg = "<div class='msg'><i class='fa fa-refresh fa-spin'></i> Fetching rows...</div>";
|
||||||
showMsg(msg, false, false, 0)
|
showMsg(msg, false, false, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('#history_table').on('click', 'td.modal-control', function () {
|
||||||
|
var tr = $(this).parents('tr');
|
||||||
|
var row = history_table.row(tr);
|
||||||
|
var rowData = row.data();
|
||||||
|
|
||||||
|
function showStreamDetails() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_stream_data',
|
||||||
|
data: { row_id: rowData['id'], user: rowData['friendly_name'] },
|
||||||
|
cache: false,
|
||||||
|
async: true,
|
||||||
|
complete: function (xhr, status) {
|
||||||
|
$("#info-modal").html(xhr.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
showStreamDetails();
|
||||||
|
});
|
|
@ -1,3 +1,5 @@
|
||||||
|
var users_to_purge = [];
|
||||||
|
|
||||||
users_list_table_options = {
|
users_list_table_options = {
|
||||||
"language": {
|
"language": {
|
||||||
"search": "Search: ",
|
"search": "Search: ",
|
||||||
|
@ -187,6 +189,11 @@ users_list_table_options = {
|
||||||
"preDrawCallback": function(settings) {
|
"preDrawCallback": function(settings) {
|
||||||
var msg = "<div class='msg'><i class='fa fa-refresh fa-spin'></i> Fetching rows...</div>";
|
var msg = "<div class='msg'><i class='fa fa-refresh fa-spin'></i> Fetching rows...</div>";
|
||||||
showMsg(msg, false, false, 0)
|
showMsg(msg, false, false, 0)
|
||||||
|
},
|
||||||
|
"rowCallback": function (row, rowData) {
|
||||||
|
if ($.inArray(rowData['user_id'], users_to_purge) !== -1) {
|
||||||
|
$(row).find('button[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,9 +278,11 @@ $('#users_list_table').on('click', 'td.edit-control > .edit-user-toggles > butto
|
||||||
var row = users_list_table.row(tr);
|
var row = users_list_table.row(tr);
|
||||||
var rowData = row.data();
|
var rowData = row.data();
|
||||||
|
|
||||||
if ($(this).hasClass('active')) {
|
var index = $.inArray(rowData['user_id'], users_to_purge);
|
||||||
$(this).toggleClass('btn-warning').toggleClass('btn-danger');
|
if (index === -1) {
|
||||||
|
users_to_purge.push(rowData['user_id']);
|
||||||
} else {
|
} else {
|
||||||
$(this).toggleClass('btn-danger').toggleClass('btn-warning');
|
users_to_purge.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
$(this).toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
});
|
});
|
78
data/interfaces/default/library_stats.html
Normal file
78
data/interfaces/default/library_stats.html
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<%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: library_stats.html
|
||||||
|
Version: 0.1
|
||||||
|
Variable names: data [array]
|
||||||
|
|
||||||
|
data[array_index] :: Usable parameters
|
||||||
|
|
||||||
|
data['type'] Returns the type of the library. Either 'movie', 'show', 'photo', or 'artist'.
|
||||||
|
data['rows'] Returns an array containing stat data
|
||||||
|
|
||||||
|
data[array_index]['rows'] :: Usable parameters
|
||||||
|
|
||||||
|
title Returns the title of the library.
|
||||||
|
thumb Returns the thumb of the library.
|
||||||
|
count Returns the number of items in the library.
|
||||||
|
count_type Returns the sorting type for the library
|
||||||
|
|
||||||
|
== Only if 'type' is 'show'
|
||||||
|
episode_count Return the number of episodes in the library.
|
||||||
|
episode_count_type Return the sorting type for the episodes.
|
||||||
|
|
||||||
|
== Only if 'type' is 'artist'
|
||||||
|
album_count Return the number of episodes in the library.
|
||||||
|
album_count_type Return the sorting type for the episodes.
|
||||||
|
|
||||||
|
DOCUMENTATION :: END
|
||||||
|
</%doc>
|
||||||
|
|
||||||
|
% if data:
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
% for library in data:
|
||||||
|
<div class="home-platforms-instance">
|
||||||
|
<li>
|
||||||
|
<div class="home-platforms-instance-info">
|
||||||
|
<div class="home-platforms-instance-name">
|
||||||
|
<h4>${library['rows']['title']}</h4>
|
||||||
|
<h5>${library['rows']['count_type']}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="home-platforms-instance-playcount">
|
||||||
|
<h3>${library['rows']['count']}</h3>
|
||||||
|
<p> items</p>
|
||||||
|
</div>
|
||||||
|
% if library['type'] == 'show':
|
||||||
|
<div class="home-platforms-instance-name2">
|
||||||
|
<h5>${library['rows']['episode_count_type']}</h5>
|
||||||
|
<h3>${library['rows']['episode_count']}</h3>
|
||||||
|
<p> items</p>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% if library['type'] == 'artist':
|
||||||
|
<div class="home-platforms-instance-name2">
|
||||||
|
<h5>${library['rows']['album_count_type']}</h5>
|
||||||
|
<h3>${library['rows']['album_count']}</h3>
|
||||||
|
<p> items</p>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
% if library['rows']['thumb']:
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-library-thumb" style="background-image: url(pms_image_proxy?img=${library['rows']['thumb']}&width=300&height=300&fallback=poster);"></div>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
|
<div class="home-platforms-instance-poster">
|
||||||
|
<div class="home-platforms-library-thumb" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
% endfor
|
||||||
|
</ul>
|
||||||
|
% else:
|
||||||
|
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
||||||
|
</div><br>
|
||||||
|
% endif
|
|
@ -91,11 +91,22 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="home_stats_length">Time Frame</label>
|
<label for="home_stats_length">Time Frame</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="home_stats_length" name="home_stats_length" value="${config['home_stats_length']}" size="3" data-parsley-min="0" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="home_stats_length" name="home_stats_length" value="${config['home_stats_length']}" size="3" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#home_stats_length_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="home_stats_length_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Specify the number of days for the statistics on the home page. Default is 30 days.</p>
|
<p class="help-block">Specify the number of days for the statistics on the home page. Default is 30 days.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="home_stats_count">Top Lists</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2">
|
||||||
|
<input type="text" class="form-control" data-parsley-type="integer" id="home_stats_count" name="home_stats_count" value="${config['home_stats_count']}" size="3" data-parsley-range="[0,10]" data-parsley-trigger="change" data-parsley-errors-container="#home_stats_count_error" required>
|
||||||
|
</div>
|
||||||
|
<div id="home_stats_count_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">Specify the number of items to show in the top lists for the statistics on the home page. Max is 10 items, default is 5 items, 0 to disable.</p>
|
||||||
|
</div>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="home_stats_type" name="home_stats_type" value="1" ${config['home_stats_type']}> Use play duration
|
<input type="checkbox" id="home_stats_type" name="home_stats_type" value="1" ${config['home_stats_type']}> Use play duration
|
||||||
|
@ -122,8 +133,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="http_port">HTTP Port</label>
|
<label for="http_port">HTTP Port</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="http_port" name="http_port" value="${config['http_port']}" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="http_port" name="http_port" value="${config['http_port']}" data-parsley-trigger="change" data-parsley-errors-container="#http_port_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="http_port_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Port to bind web server to. Note that ports below 1024 may require root.</p>
|
<p class="help-block">Port to bind web server to. Note that ports below 1024 may require root.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -223,8 +235,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="pms_port">Plex Port</label>
|
<label for="pms_port">Plex Port</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input data-parsley-type="integer" class="pms-settings form-control" type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" data-parsley-trigger="change" required>
|
<input data-parsley-type="integer" class="pms-settings form-control" type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" data-parsley-trigger="change" data-parsley-errors-container="#pms_port_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="pms_port_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Port that Plex Media Server is listening on.</p>
|
<p class="help-block">Port that Plex Media Server is listening on.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -286,8 +299,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="refresh_users_interval">User list Refresh Interval</label>
|
<label for="refresh_users_interval">User list Refresh Interval</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="refresh_users_interval" name="refresh_users_interval" value="${config['refresh_users_interval']}" size="5" data-parsley-range="[1,24]" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="refresh_users_interval" name="refresh_users_interval" value="${config['refresh_users_interval']}" size="5" data-parsley-range="[1,24]" data-parsley-trigger="change" data-parsley-errors-container="#refresh_users_interval_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="refresh_users_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">The interval (in hours) PlexPy will request an updated friends list from Plex.tv. 1 minimum, 24 maximum.</p>
|
<p class="help-block">The interval (in hours) PlexPy will request an updated friends list from Plex.tv. 1 minimum, 24 maximum.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -328,10 +342,11 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="monitoring_interval">Monitoring Interval</label>
|
<label for="monitoring_interval">Monitoring Interval</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" data-parsley-errors-container="#monitoring_interval_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="monitoring_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">The interval (in seconds) PlexPy will ping your Plex Server. Min 30 seconds, Recommended 60 seconds.</p>
|
<p class="help-block">The interval (in seconds) PlexPy will ping your Plex Server. Min 30 seconds, recommended 60 seconds.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="padded-header">
|
<div class="padded-header">
|
||||||
|
@ -344,11 +359,12 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<p class="help-block">Keep records of all video items played from your Plex Media Server.</p>
|
<p class="help-block">Keep records of all video items played from your Plex Media Server.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="monitoring_interval">Ignore Interval</label>
|
<label for="logging_ignore_interval">Ignore Interval</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="0" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#logging_ignore_interval_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="logging_ignore_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">The interval (in seconds) PlexPy will wait for a video item to be active before logging it. 0 to disable.</p>
|
<p class="help-block">The interval (in seconds) PlexPy will wait for a video item to be active before logging it. 0 to disable.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -380,8 +396,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="buffer_threshold">Buffer Threshold</label>
|
<label for="buffer_threshold">Buffer Threshold</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[0,50]" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[0,50]" data-parsley-trigger="change" data-parsley-errors-container="#buffer_threshold_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="buffer_threshold_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering. 0 to disable buffer warnings.</p>
|
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering. 0 to disable buffer warnings.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -389,8 +406,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="buffer_wait">Buffer Wait</label>
|
<label for="buffer_wait">Buffer Wait</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_wait" name="buffer_wait" value="${config['buffer_wait']}" data-parsley-min="0" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_wait" name="buffer_wait" value="${config['buffer_wait']}" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#buffer_wait_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="buffer_wait_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">The value (in seconds) PlexPy should wait before triggering the next buffer warning. 0 to always trigger.</p>
|
<p class="help-block">The value (in seconds) PlexPy should wait before triggering the next buffer warning. 0 to always trigger.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -421,8 +439,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<label for="notify_watched_percent">Watched Percent</label>
|
<label for="notify_watched_percent">Watched Percent</label>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" required>
|
<input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#notify_watched_percent_error" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="notify_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">Set the progress percentage of when a watched notification should be triggered. Minimum 50, Maximum 95.</p>
|
<p class="help-block">Set the progress percentage of when a watched notification should be triggered. Minimum 50, Maximum 95.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -552,7 +571,7 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<h3>Notification Agents</h3>
|
<h3>Notification Agents</h3>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
Toggle the desired notification options by clicking the bolt icon and configure it by selecting the settings icon to the right.
|
Toggle the desired notification options by clicking the bell icon and configure it by clicking the settings icon to the right.
|
||||||
</p>
|
</p>
|
||||||
<br/>
|
<br/>
|
||||||
<ul class="stacked-configs list-unstyled">
|
<ul class="stacked-configs list-unstyled">
|
||||||
|
@ -560,9 +579,9 @@ available_notification_agents = notifiers.available_notification_agents()
|
||||||
<li>
|
<li>
|
||||||
<span>
|
<span>
|
||||||
% if agent['on_play'] or agent['on_stop'] or agent['on_pause'] or agent['on_resume'] or agent['on_buffer'] or agent['on_watched']:
|
% if agent['on_play'] or agent['on_stop'] or agent['on_pause'] or agent['on_resume'] or agent['on_buffer'] or agent['on_watched']:
|
||||||
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left active" data-toggle="modal"><i class="fa fa-lg fa-flash"></i></a>
|
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left active" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
||||||
% else:
|
% else:
|
||||||
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left" data-toggle="modal"><i class="fa fa-lg fa-flash"></i></a>
|
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
|
||||||
% endif
|
% endif
|
||||||
${agent['name']}
|
${agent['name']}
|
||||||
% if agent['has_config']:
|
% if agent['has_config']:
|
||||||
|
|
|
@ -54,6 +54,7 @@ DOCUMENTATION :: END
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<h4><strong>Stream Details</strong></h4>
|
<h4><strong>Stream Details</strong></h4>
|
||||||
|
% if data['media_type'] != 'track':
|
||||||
<h5>Video</h5>
|
<h5>Video</h5>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
% if data['transcode_video_dec'] != 'direct play':
|
% if data['transcode_video_dec'] != 'direct play':
|
||||||
|
@ -74,6 +75,7 @@ DOCUMENTATION :: END
|
||||||
<li>Video Height: <strong>${data['height']}</strong></li>
|
<li>Video Height: <strong>${data['height']}</strong></li>
|
||||||
% endif
|
% endif
|
||||||
</ul>
|
</ul>
|
||||||
|
% endif
|
||||||
<h5>Audio</h5>
|
<h5>Audio</h5>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
% if data['transcode_audio_dec'] != 'direct play':
|
% if data['transcode_audio_dec'] != 'direct play':
|
||||||
|
@ -91,11 +93,14 @@ DOCUMENTATION :: END
|
||||||
<h4><strong>Media Source Details</strong></h4>
|
<h4><strong>Media Source Details</strong></h4>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>Container: <strong>${data['container']}</strong></li>
|
<li>Container: <strong>${data['container']}</strong></li>
|
||||||
|
% if data['media_type'] != 'track':
|
||||||
<li>Resolution: <strong>${data['height']}p</strong></li>
|
<li>Resolution: <strong>${data['height']}p</strong></li>
|
||||||
|
% endif
|
||||||
<li>Bitrate: <strong>${data['bitrate']} kbps</strong></li>
|
<li>Bitrate: <strong>${data['bitrate']} kbps</strong></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
% if data['media_type'] != 'track':
|
||||||
<h4><strong>Video Source Details</strong></h4>
|
<h4><strong>Video Source Details</strong></h4>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>Width: <strong>${data['width']}</strong></li>
|
<li>Width: <strong>${data['width']}</strong></li>
|
||||||
|
@ -104,6 +109,7 @@ DOCUMENTATION :: END
|
||||||
<li>Video Frame Rate: <strong>${data['video_framerate']}</strong></li>
|
<li>Video Frame Rate: <strong>${data['video_framerate']}</strong></li>
|
||||||
<li>Video Codec: <strong>${data['video_codec']}</strong></li>
|
<li>Video Codec: <strong>${data['video_codec']}</strong></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
% endif
|
||||||
<h4><strong>Audio Source Details</strong></h4>
|
<h4><strong>Audio Source Details</strong></h4>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>Audio Codec: <strong>${data['audio_codec']}</strong></li>
|
<li>Audio Codec: <strong>${data['audio_codec']}</strong></li>
|
||||||
|
|
|
@ -154,13 +154,11 @@ from plexpy import helpers
|
||||||
</strong></span>
|
</strong></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<span data-toggle="popover" data-placement="left" data-content="Select rows to delete. Data is deleted upon exiting delete mode." id="delete-message">
|
<div class="colvis-button-bar hidden-xs" id="button-bar-history"></div>
|
||||||
<button class="btn btn-danger" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
||||||
<i class="fa fa-trash-o"></i> Delete mode
|
<i class="fa fa-trash-o"></i> Delete mode
|
||||||
</button> 
|
</button>
|
||||||
</span>
|
<div class="alert alert-danger alert-edit" role="alert" id="row-edit-mode-alert"><i class="fa fa-exclamation-triangle"></i> Select rows to delete. Data is deleted upon exiting delete mode.</div>
|
||||||
<div class="colvis-button-bar hidden-xs" id="button-bar-history">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
|
@ -170,8 +168,8 @@ from plexpy import helpers
|
||||||
<th align='left' id="delete">Delete</th>
|
<th align='left' id="delete">Delete</th>
|
||||||
<th align='left' id="time">Time</th>
|
<th align='left' id="time">Time</th>
|
||||||
<th align='left' id="friendly_name">User</th>
|
<th align='left' id="friendly_name">User</th>
|
||||||
<th align='left' id="platform">Platform</th>
|
|
||||||
<th align='left' id="ip_address">IP Address</th>
|
<th align='left' id="ip_address">IP Address</th>
|
||||||
|
<th align='left' id="platform">Platform</th>
|
||||||
<th align='left' id="title">Title</th>
|
<th align='left' id="title">Title</th>
|
||||||
<th align='left' id="started">Started</th>
|
<th align='left' id="started">Started</th>
|
||||||
<th align='left' id="paused_counter">Paused</th>
|
<th align='left' id="paused_counter">Paused</th>
|
||||||
|
@ -390,7 +388,7 @@ from plexpy import helpers
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#row-edit-mode').on('click', function() {
|
$('#row-edit-mode').on('click', function() {
|
||||||
$('#delete-message').popover();
|
$('#row-edit-mode-alert').fadeIn(200);
|
||||||
|
|
||||||
if ($(this).hasClass('active')) {
|
if ($(this).hasClass('active')) {
|
||||||
if (history_to_delete.length > 0) {
|
if (history_to_delete.length > 0) {
|
||||||
|
@ -403,7 +401,7 @@ from plexpy import helpers
|
||||||
data: { row_id: history_to_delete[i] },
|
data: { row_id: history_to_delete[i] },
|
||||||
async: true,
|
async: true,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
var msg = "User history purged";
|
var msg = "History deleted";
|
||||||
showMsg(msg, false, true, 2000);
|
showMsg(msg, false, true, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -413,13 +411,14 @@ from plexpy import helpers
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.delete-control').each(function () {
|
$('.delete-control').each(function () {
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
|
$('#row-edit-mode-alert').fadeOut(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
history_to_delete = [];
|
history_to_delete = [];
|
||||||
$('.delete-control').each(function() {
|
$('.delete-control').each(function() {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
$(this).removeClass('hidden');
|
$(this).removeClass('hidden');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
<span><i class="fa fa-group"></i> All Users</span>
|
<span><i class="fa fa-group"></i> All Users</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<span data-toggle="popover" data-placement="left" data-content="Data purging does not occur until after exiting edit mode." id="purge-message">
|
<button class="btn btn-dark refresh-users-button" id="refresh-users-list"><i class="fa fa-refresh"></i> Refresh users</button>
|
||||||
<button class="btn btn-dark" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
|
||||||
<i class="fa fa-pencil"></i> Edit mode
|
<i class="fa fa-pencil"></i> Edit mode
|
||||||
</button> 
|
</button> 
|
||||||
</span>
|
<div class="alert alert-danger alert-edit" role="alert" id="row-edit-mode-alert"><i class="fa fa-exclamation-triangle"></i> Select rows to delete. Data is deleted upon exiting delete mode.</div>
|
||||||
<button class="btn btn-dark" id="refresh-users-list"><i class="fa fa-refresh"></i> Refresh users</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='table-card-back'>
|
<div class='table-card-back'>
|
||||||
|
@ -85,20 +84,19 @@
|
||||||
|
|
||||||
clearSearchButton('users_list_table', users_list_table);
|
clearSearchButton('users_list_table', users_list_table);
|
||||||
|
|
||||||
var users_to_purge = [];
|
|
||||||
$('#row-edit-mode').on('click', function () {
|
$('#row-edit-mode').on('click', function () {
|
||||||
$('#purge-message').popover();
|
$('#row-edit-mode-alert').fadeIn(200);
|
||||||
|
$('#users-to-delete').html('');
|
||||||
|
|
||||||
if ($(this).hasClass('active')) {
|
if ($(this).hasClass('active')) {
|
||||||
users_to_purge = [];
|
|
||||||
ul = $('#users-to-delete');
|
|
||||||
ul.html('');
|
|
||||||
$('.edit-control button.btn-danger').map(function () {
|
|
||||||
users_to_purge.push($(this).attr('data-id'));
|
|
||||||
ul.append('<li>' + $('div[data-id=' + $(this).attr('data-id') + '] > input').val() + '</li>')
|
|
||||||
});
|
|
||||||
if (users_to_purge.length > 0) {
|
if (users_to_purge.length > 0) {
|
||||||
$('#users-to-delete').append
|
$('.edit-control').each(function () {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < users_to_purge.length; i++) {
|
||||||
|
$('#users-to-delete').append('<li>' + $('div[data-id=' + users_to_purge[i] + '] > input').val() + '</li>');
|
||||||
|
}
|
||||||
$('#confirm-modal').modal();
|
$('#confirm-modal').modal();
|
||||||
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
||||||
for (var i = 0; i < users_to_purge.length; i++) {
|
for (var i = 0; i < users_to_purge.length; i++) {
|
||||||
|
@ -118,35 +116,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.edit-control').each(function () {
|
$('.edit-control').each(function () {
|
||||||
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
});
|
$('#row-edit-mode-alert').fadeOut(200);
|
||||||
$('.edit-user-control > .edit-user-name').each(function () {
|
|
||||||
a = $(this).children('a');
|
|
||||||
input = $(this).children('input');
|
|
||||||
a.text(input.val());
|
|
||||||
a.removeClass('hidden');
|
|
||||||
input.addClass('hidden');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
users_to_purge = [];
|
||||||
$('.edit-control').each(function () {
|
$('.edit-control').each(function () {
|
||||||
|
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
|
||||||
$(this).removeClass('hidden');
|
$(this).removeClass('hidden');
|
||||||
});
|
});
|
||||||
$('.edit-user-control > .edit-user-name').each(function () {
|
|
||||||
$(this).children('a').addClass('hidden');
|
|
||||||
$(this).children('input').removeClass('hidden');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).resize(function () {
|
|
||||||
if ($('.popover').popover().is(':visible')) {
|
|
||||||
var popover = $('.popover');
|
|
||||||
popover.addClass("noTransition");
|
|
||||||
$('#purge-message').popover('show');
|
|
||||||
popover.removeClass("noTransition");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -588,6 +588,12 @@ def dbcheck():
|
||||||
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
|
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Add "Local" user to database as default unauthenticated user.
|
||||||
|
result = c_db.execute('SELECT id FROM users WHERE username = "Local"')
|
||||||
|
if not result.fetchone():
|
||||||
|
logger.debug(u'User "Local" does not exist. Adding user.')
|
||||||
|
c_db.execute('INSERT INTO users (user_id, username) VALUES (0, "Local")')
|
||||||
|
|
||||||
conn_db.commit()
|
conn_db.commit()
|
||||||
c_db.close()
|
c_db.close()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import plexpy.logger
|
import plexpy.logger
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -84,6 +84,7 @@ _CONFIG_DEFINITIONS = {
|
||||||
'GROWL_ON_WATCHED': (int, 'Growl', 0),
|
'GROWL_ON_WATCHED': (int, 'Growl', 0),
|
||||||
'HOME_STATS_LENGTH': (int, 'General', 30),
|
'HOME_STATS_LENGTH': (int, 'General', 30),
|
||||||
'HOME_STATS_TYPE': (int, 'General', 0),
|
'HOME_STATS_TYPE': (int, 'General', 0),
|
||||||
|
'HOME_STATS_COUNT': (int, 'General', 5),
|
||||||
'HTTPS_CERT': (str, 'General', ''),
|
'HTTPS_CERT': (str, 'General', ''),
|
||||||
'HTTPS_KEY': (str, 'General', ''),
|
'HTTPS_KEY': (str, 'General', ''),
|
||||||
'HTTP_HOST': (str, 'General', '0.0.0.0'),
|
'HTTP_HOST': (str, 'General', '0.0.0.0'),
|
||||||
|
|
|
@ -55,6 +55,7 @@ class DataFactory(object):
|
||||||
(CASE WHEN session_history_metadata.duration IS NULL THEN 1.0 ELSE \
|
(CASE WHEN session_history_metadata.duration IS NULL THEN 1.0 ELSE \
|
||||||
session_history_metadata.duration * 1.0 END) * 100) as percent_complete',
|
session_history_metadata.duration * 1.0 END) * 100) as percent_complete',
|
||||||
'session_history.grandparent_rating_key as grandparent_rating_key',
|
'session_history.grandparent_rating_key as grandparent_rating_key',
|
||||||
|
'session_history.parent_rating_key as parent_rating_key',
|
||||||
'session_history.rating_key as rating_key',
|
'session_history.rating_key as rating_key',
|
||||||
'session_history.user',
|
'session_history.user',
|
||||||
'session_history_metadata.media_type',
|
'session_history_metadata.media_type',
|
||||||
|
@ -112,6 +113,7 @@ class DataFactory(object):
|
||||||
"duration": item["duration"],
|
"duration": item["duration"],
|
||||||
"percent_complete": item["percent_complete"],
|
"percent_complete": item["percent_complete"],
|
||||||
"grandparent_rating_key": item["grandparent_rating_key"],
|
"grandparent_rating_key": item["grandparent_rating_key"],
|
||||||
|
"parent_rating_key": item["parent_rating_key"],
|
||||||
"rating_key": item["rating_key"],
|
"rating_key": item["rating_key"],
|
||||||
"user": item["user"],
|
"user": item["user"],
|
||||||
"media_type": item["media_type"],
|
"media_type": item["media_type"],
|
||||||
|
@ -129,7 +131,7 @@ class DataFactory(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def get_home_stats(self, time_range='30', stat_type='0'):
|
def get_home_stats(self, time_range='30', stat_type='0', stat_count='5'):
|
||||||
monitor_db = database.MonitorDatabase()
|
monitor_db = database.MonitorDatabase()
|
||||||
|
|
||||||
if not time_range.isdigit():
|
if not time_range.isdigit():
|
||||||
|
@ -137,8 +139,11 @@ class DataFactory(object):
|
||||||
|
|
||||||
sort_type = 'total_plays' if stat_type == '0' else 'total_duration'
|
sort_type = 'total_plays' if stat_type == '0' else 'total_duration'
|
||||||
|
|
||||||
|
if not time_range.isdigit():
|
||||||
|
stat_count = '5'
|
||||||
|
|
||||||
# This actually determines the output order in the home page
|
# This actually determines the output order in the home page
|
||||||
stats_queries = ["top_tv", "popular_tv", "top_movies", "popular_movies", "top_users", "top_platforms"]
|
stats_queries = ["top_tv", "popular_tv", "top_movies", "popular_movies", "top_users", "top_platforms", "last_watched"]
|
||||||
home_stats = []
|
home_stats = []
|
||||||
|
|
||||||
for stat in stats_queries:
|
for stat in stats_queries:
|
||||||
|
@ -161,7 +166,7 @@ class DataFactory(object):
|
||||||
'>= datetime("now", "-%s days", "localtime") ' \
|
'>= datetime("now", "-%s days", "localtime") ' \
|
||||||
'AND session_history_metadata.media_type = "episode" ' \
|
'AND session_history_metadata.media_type = "episode" ' \
|
||||||
'GROUP BY session_history_metadata.grandparent_title ' \
|
'GROUP BY session_history_metadata.grandparent_title ' \
|
||||||
'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type)
|
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -207,7 +212,7 @@ class DataFactory(object):
|
||||||
'>= datetime("now", "-%s days", "localtime") ' \
|
'>= datetime("now", "-%s days", "localtime") ' \
|
||||||
'AND session_history_metadata.media_type = "movie" ' \
|
'AND session_history_metadata.media_type = "movie" ' \
|
||||||
'GROUP BY session_history_metadata.full_title ' \
|
'GROUP BY session_history_metadata.full_title ' \
|
||||||
'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type)
|
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -251,7 +256,7 @@ class DataFactory(object):
|
||||||
'AND session_history_metadata.media_type = "episode" ' \
|
'AND session_history_metadata.media_type = "episode" ' \
|
||||||
'GROUP BY session_history_metadata.grandparent_title ' \
|
'GROUP BY session_history_metadata.grandparent_title ' \
|
||||||
'ORDER BY users_watched DESC, total_plays DESC ' \
|
'ORDER BY users_watched DESC, total_plays DESC ' \
|
||||||
'LIMIT 10' % time_range
|
'LIMIT %s' % (time_range, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -293,7 +298,7 @@ class DataFactory(object):
|
||||||
'AND session_history_metadata.media_type = "movie" ' \
|
'AND session_history_metadata.media_type = "movie" ' \
|
||||||
'GROUP BY session_history_metadata.full_title ' \
|
'GROUP BY session_history_metadata.full_title ' \
|
||||||
'ORDER BY users_watched DESC, total_plays DESC ' \
|
'ORDER BY users_watched DESC, total_plays DESC ' \
|
||||||
'LIMIT 10' % time_range
|
'LIMIT %s' % (time_range, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -338,7 +343,7 @@ class DataFactory(object):
|
||||||
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||||
'datetime("now", "-%s days", "localtime") '\
|
'datetime("now", "-%s days", "localtime") '\
|
||||||
'GROUP BY session_history.user_id ' \
|
'GROUP BY session_history.user_id ' \
|
||||||
'ORDER BY %s DESC LIMIT 10' % (time_range, sort_type)
|
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -356,7 +361,7 @@ class DataFactory(object):
|
||||||
'total_plays': item[2],
|
'total_plays': item[2],
|
||||||
'total_duration': item[3],
|
'total_duration': item[3],
|
||||||
'last_play': item[4],
|
'last_play': item[4],
|
||||||
'thumb': user_thumb,
|
'user_thumb': user_thumb,
|
||||||
'grandparent_thumb': '',
|
'grandparent_thumb': '',
|
||||||
'users_watched': '',
|
'users_watched': '',
|
||||||
'rating_key': '',
|
'rating_key': '',
|
||||||
|
@ -386,7 +391,7 @@ class DataFactory(object):
|
||||||
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
|
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
|
||||||
'>= datetime("now", "-%s days", "localtime") ' \
|
'>= datetime("now", "-%s days", "localtime") ' \
|
||||||
'GROUP BY session_history.platform ' \
|
'GROUP BY session_history.platform ' \
|
||||||
'ORDER BY total_plays DESC' % time_range
|
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
|
||||||
result = monitor_db.select(query)
|
result = monitor_db.select(query)
|
||||||
except:
|
except:
|
||||||
logger.warn("Unable to execute database query.")
|
logger.warn("Unable to execute database query.")
|
||||||
|
@ -413,6 +418,59 @@ class DataFactory(object):
|
||||||
'stat_type': sort_type,
|
'stat_type': sort_type,
|
||||||
'rows': top_platform})
|
'rows': top_platform})
|
||||||
|
|
||||||
|
elif 'last_watched' in stat:
|
||||||
|
last_watched = []
|
||||||
|
try:
|
||||||
|
query = 'SELECT session_history_metadata.id, ' \
|
||||||
|
'session_history.user, ' \
|
||||||
|
'(case when users.friendly_name is null then session_history.user else ' \
|
||||||
|
'users.friendly_name end) as friendly_name,' \
|
||||||
|
'users.user_id, ' \
|
||||||
|
'users.custom_avatar_url as user_thumb, ' \
|
||||||
|
'session_history_metadata.full_title, ' \
|
||||||
|
'session_history_metadata.rating_key, ' \
|
||||||
|
'session_history_metadata.thumb, ' \
|
||||||
|
'session_history_metadata.grandparent_thumb, ' \
|
||||||
|
'MAX(session_history.started) as last_watch, ' \
|
||||||
|
'session_history.player as platform ' \
|
||||||
|
'FROM session_history_metadata ' \
|
||||||
|
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
|
||||||
|
'LEFT OUTER JOIN users ON session_history.user_id = users.user_id ' \
|
||||||
|
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
|
||||||
|
'>= datetime("now", "-%s days", "localtime") ' \
|
||||||
|
'AND (session_history_metadata.media_type = "movie" ' \
|
||||||
|
'OR session_history_metadata.media_type = "episode") ' \
|
||||||
|
'GROUP BY session_history_metadata.full_title ' \
|
||||||
|
'ORDER BY last_watch DESC ' \
|
||||||
|
'LIMIT %s' % (time_range, stat_count)
|
||||||
|
result = monitor_db.select(query)
|
||||||
|
except:
|
||||||
|
logger.warn("Unable to execute database query.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
for item in result:
|
||||||
|
if not item[8] or item[8] == '':
|
||||||
|
thumb = item[7]
|
||||||
|
else:
|
||||||
|
thumb = item[8]
|
||||||
|
|
||||||
|
row = {'row_id': item[0],
|
||||||
|
'user': item[1],
|
||||||
|
'friendly_name': item[2],
|
||||||
|
'user_id': item[3],
|
||||||
|
'user_thumb': item[4],
|
||||||
|
'title': item[5],
|
||||||
|
'rating_key': item[6],
|
||||||
|
'thumb': thumb,
|
||||||
|
'grandparent_thumb': item[8],
|
||||||
|
'last_watch': item[9],
|
||||||
|
'platform_type': item[10],
|
||||||
|
}
|
||||||
|
last_watched.append(row)
|
||||||
|
|
||||||
|
home_stats.append({'stat_id': stat,
|
||||||
|
'rows': last_watched})
|
||||||
|
|
||||||
return home_stats
|
return home_stats
|
||||||
|
|
||||||
def get_stream_details(self, row_id=None):
|
def get_stream_details(self, row_id=None):
|
||||||
|
|
|
@ -27,9 +27,8 @@ def refresh_users():
|
||||||
|
|
||||||
if len(result) > 0:
|
if len(result) > 0:
|
||||||
for item in result:
|
for item in result:
|
||||||
control_value_dict = {"username": item['username']}
|
control_value_dict = {"user_id": item['user_id']}
|
||||||
new_value_dict = {"user_id": item['user_id'],
|
new_value_dict = {"username": item['username'],
|
||||||
"username": item['username'],
|
|
||||||
"thumb": item['thumb'],
|
"thumb": item['thumb'],
|
||||||
"email": item['email'],
|
"email": item['email'],
|
||||||
"is_home_user": item['is_home_user'],
|
"is_home_user": item['is_home_user'],
|
||||||
|
|
|
@ -89,6 +89,23 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return list of seasons in requested show.
|
||||||
|
|
||||||
|
Parameters required: rating_key { ratingKey of parent }
|
||||||
|
Optional parameters: output_format { dict, json }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_season_list(self, rating_key='', output_format=''):
|
||||||
|
uri = '/library/metadata/' + rating_key + '/children'
|
||||||
|
request = self.request_handler.make_request(uri=uri,
|
||||||
|
proto=self.protocol,
|
||||||
|
request_type='GET',
|
||||||
|
output_format=output_format)
|
||||||
|
|
||||||
|
return request
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return list of episodes in requested season.
|
Return list of episodes in requested season.
|
||||||
|
|
||||||
|
@ -154,6 +171,38 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return list of libraries on server.
|
||||||
|
|
||||||
|
Optional parameters: output_format { dict, json }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_libraries_list(self, output_format=''):
|
||||||
|
uri = '/library/sections'
|
||||||
|
request = self.request_handler.make_request(uri=uri,
|
||||||
|
proto=self.protocol,
|
||||||
|
request_type='GET',
|
||||||
|
output_format=output_format)
|
||||||
|
|
||||||
|
return request
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return list of items in library on server.
|
||||||
|
|
||||||
|
Optional parameters: output_format { dict, json }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_library_list(self, section_key='', list_type='all', count='0', sort_type='', output_format=''):
|
||||||
|
uri = '/library/sections/' + section_key + '/' + list_type +'?X-Plex-Container-Start=0&X-Plex-Container-Size=' + count + sort_type
|
||||||
|
request = self.request_handler.make_request(uri=uri,
|
||||||
|
proto=self.protocol,
|
||||||
|
request_type='GET',
|
||||||
|
output_format=output_format)
|
||||||
|
|
||||||
|
return request
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return sync item details.
|
Return sync item details.
|
||||||
|
|
||||||
|
@ -552,6 +601,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
|
'user_thumb': user_details['thumb'],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
'machine_id': machine_id,
|
'machine_id': machine_id,
|
||||||
|
@ -661,6 +711,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
|
'user_thumb': user_details['thumb'],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
'machine_id': machine_id,
|
'machine_id': machine_id,
|
||||||
|
@ -668,6 +719,7 @@ class PmsConnect(object):
|
||||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||||
'title': helpers.get_xml_attr(session, 'title'),
|
'title': helpers.get_xml_attr(session, 'title'),
|
||||||
|
'year': helpers.get_xml_attr(session, 'year'),
|
||||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
||||||
|
@ -693,9 +745,13 @@ class PmsConnect(object):
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
'progress': progress,
|
'progress': progress,
|
||||||
'progress_percent': str(helpers.get_percent(progress, duration)),
|
'progress_percent': str(helpers.get_percent(progress, duration)),
|
||||||
'type': helpers.get_xml_attr(session, 'type'),
|
|
||||||
'indexes': use_indexes
|
'indexes': use_indexes
|
||||||
}
|
}
|
||||||
|
if helpers.get_xml_attr(session, 'ratingKey').isdigit():
|
||||||
|
session_output['type'] = helpers.get_xml_attr(session, 'type')
|
||||||
|
else:
|
||||||
|
session_output['type'] = 'clip'
|
||||||
|
|
||||||
elif helpers.get_xml_attr(session, 'type') == 'movie':
|
elif helpers.get_xml_attr(session, 'type') == 'movie':
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
|
@ -708,6 +764,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
|
'user_thumb': user_details['thumb'],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
'machine_id': machine_id,
|
'machine_id': machine_id,
|
||||||
|
@ -715,6 +772,7 @@ class PmsConnect(object):
|
||||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||||
'title': helpers.get_xml_attr(session, 'title'),
|
'title': helpers.get_xml_attr(session, 'title'),
|
||||||
|
'year': helpers.get_xml_attr(session, 'year'),
|
||||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
||||||
|
@ -740,9 +798,13 @@ class PmsConnect(object):
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
'progress': progress,
|
'progress': progress,
|
||||||
'progress_percent': str(helpers.get_percent(progress, duration)),
|
'progress_percent': str(helpers.get_percent(progress, duration)),
|
||||||
'type': helpers.get_xml_attr(session, 'type'),
|
|
||||||
'indexes': use_indexes
|
'indexes': use_indexes
|
||||||
}
|
}
|
||||||
|
if helpers.get_xml_attr(session, 'ratingKey').isdigit():
|
||||||
|
session_output['type'] = helpers.get_xml_attr(session, 'type')
|
||||||
|
else:
|
||||||
|
session_output['type'] = 'clip'
|
||||||
|
|
||||||
elif helpers.get_xml_attr(session, 'type') == 'clip':
|
elif helpers.get_xml_attr(session, 'type') == 'clip':
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
'media_index': helpers.get_xml_attr(session, 'index'),
|
'media_index': helpers.get_xml_attr(session, 'index'),
|
||||||
|
@ -755,6 +817,7 @@ class PmsConnect(object):
|
||||||
'user': user_details['username'],
|
'user': user_details['username'],
|
||||||
'user_id': user_details['user_id'],
|
'user_id': user_details['user_id'],
|
||||||
'friendly_name': user_details['friendly_name'],
|
'friendly_name': user_details['friendly_name'],
|
||||||
|
'user_thumb': user_details['thumb'],
|
||||||
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
|
||||||
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
|
||||||
'machine_id': machine_id,
|
'machine_id': machine_id,
|
||||||
|
@ -762,6 +825,7 @@ class PmsConnect(object):
|
||||||
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
|
||||||
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
|
||||||
'title': helpers.get_xml_attr(session, 'title'),
|
'title': helpers.get_xml_attr(session, 'title'),
|
||||||
|
'year': helpers.get_xml_attr(session, 'year'),
|
||||||
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||||
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
|
||||||
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
|
||||||
|
@ -795,6 +859,49 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return session_output
|
return session_output
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return processed and validated season list.
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_show_children(self, rating_key=''):
|
||||||
|
season_data = self.get_season_list(rating_key, output_format='xml')
|
||||||
|
|
||||||
|
try:
|
||||||
|
xml_head = season_data.getElementsByTagName('MediaContainer')
|
||||||
|
except:
|
||||||
|
logger.warn("Unable to parse XML for get_season_list.")
|
||||||
|
return []
|
||||||
|
|
||||||
|
season_list = []
|
||||||
|
|
||||||
|
for a in xml_head:
|
||||||
|
if a.getAttribute('size'):
|
||||||
|
if a.getAttribute('size') == '0':
|
||||||
|
logger.debug(u"No season data.")
|
||||||
|
season_list = {'season_count': '0',
|
||||||
|
'season_list': []
|
||||||
|
}
|
||||||
|
return season_list
|
||||||
|
|
||||||
|
if a.getElementsByTagName('Directory'):
|
||||||
|
result_data = a.getElementsByTagName('Directory')
|
||||||
|
for result in result_data:
|
||||||
|
season_output = {'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
|
||||||
|
'index': helpers.get_xml_attr(result, 'index'),
|
||||||
|
'title': helpers.get_xml_attr(result, 'title'),
|
||||||
|
'thumb': helpers.get_xml_attr(result, 'thumb'),
|
||||||
|
'parent_thumb': helpers.get_xml_attr(a, 'thumb')
|
||||||
|
}
|
||||||
|
season_list.append(season_output)
|
||||||
|
|
||||||
|
output = {'season_count': helpers.get_xml_attr(xml_head[0], 'size'),
|
||||||
|
'title': helpers.get_xml_attr(xml_head[0], 'title2'),
|
||||||
|
'season_list': season_list
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return processed and validated episode list.
|
Return processed and validated episode list.
|
||||||
|
|
||||||
|
@ -914,6 +1021,150 @@ class PmsConnect(object):
|
||||||
logger.debug(u"Server preferences queried but no parameter received.")
|
logger.debug(u"Server preferences queried but no parameter received.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return processed and validated server libraries list.
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_server_children(self):
|
||||||
|
libraries_data = self.get_libraries_list(output_format='xml')
|
||||||
|
|
||||||
|
try:
|
||||||
|
xml_head = libraries_data.getElementsByTagName('MediaContainer')
|
||||||
|
except:
|
||||||
|
logger.warn("Unable to parse XML for get_libraries_list.")
|
||||||
|
return []
|
||||||
|
|
||||||
|
libraries_list = []
|
||||||
|
|
||||||
|
for a in xml_head:
|
||||||
|
if a.getAttribute('size'):
|
||||||
|
if a.getAttribute('size') == '0':
|
||||||
|
logger.debug(u"No libraries data.")
|
||||||
|
libraries_list = {'libraries_count': '0',
|
||||||
|
'libraries_list': []
|
||||||
|
}
|
||||||
|
return libraries_list
|
||||||
|
|
||||||
|
if a.getElementsByTagName('Directory'):
|
||||||
|
result_data = a.getElementsByTagName('Directory')
|
||||||
|
for result in result_data:
|
||||||
|
libraries_output = {'key': helpers.get_xml_attr(result, 'key'),
|
||||||
|
'type': helpers.get_xml_attr(result, 'type'),
|
||||||
|
'title': helpers.get_xml_attr(result, 'title'),
|
||||||
|
'thumb': helpers.get_xml_attr(result, 'thumb')
|
||||||
|
}
|
||||||
|
libraries_list.append(libraries_output)
|
||||||
|
|
||||||
|
output = {'libraries_count': helpers.get_xml_attr(xml_head[0], 'size'),
|
||||||
|
'title': helpers.get_xml_attr(xml_head[0], 'title1'),
|
||||||
|
'libraries_list': libraries_list
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return processed and validated server library items list.
|
||||||
|
|
||||||
|
Parameters required: library_type { movie, show, episode, artist }
|
||||||
|
section_key { unique library key }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_library_children(self, library_type='', section_key='', list_type='all', sort_type = ''):
|
||||||
|
|
||||||
|
# Currently only grab the library with 1 items so 'size' is not 0
|
||||||
|
count = '1'
|
||||||
|
|
||||||
|
if library_type == 'movie':
|
||||||
|
sort_type = '&type=1'
|
||||||
|
elif library_type == 'show':
|
||||||
|
sort_type = '&type=2'
|
||||||
|
elif library_type == 'episode':
|
||||||
|
sort_type = '&type=4'
|
||||||
|
elif library_type == 'album':
|
||||||
|
list_type = 'albums'
|
||||||
|
|
||||||
|
library_data = self.get_library_list(section_key, list_type, count, sort_type, output_format='xml')
|
||||||
|
|
||||||
|
try:
|
||||||
|
xml_head = library_data.getElementsByTagName('MediaContainer')
|
||||||
|
except:
|
||||||
|
logger.warn("Unable to parse XML for get_library_children.")
|
||||||
|
return []
|
||||||
|
|
||||||
|
library_list = []
|
||||||
|
|
||||||
|
for a in xml_head:
|
||||||
|
if a.getAttribute('size'):
|
||||||
|
if a.getAttribute('size') == '0':
|
||||||
|
logger.debug(u"No library data.")
|
||||||
|
library_list = {'library_count': '0',
|
||||||
|
'library_list': []
|
||||||
|
}
|
||||||
|
return library_list
|
||||||
|
|
||||||
|
if a.getElementsByTagName('Directory'):
|
||||||
|
result_data = a.getElementsByTagName('Directory')
|
||||||
|
for result in result_data:
|
||||||
|
library_output = {'key': helpers.get_xml_attr(result, 'key'),
|
||||||
|
'type': helpers.get_xml_attr(result, 'type'),
|
||||||
|
'title': helpers.get_xml_attr(result, 'title'),
|
||||||
|
'thumb': helpers.get_xml_attr(result, 'thumb')
|
||||||
|
}
|
||||||
|
library_list.append(library_output)
|
||||||
|
|
||||||
|
output = {'library_count': helpers.get_xml_attr(xml_head[0], 'totalSize'),
|
||||||
|
'count_type': helpers.get_xml_attr(xml_head[0], 'title2'),
|
||||||
|
'library_list': library_list
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
"""
|
||||||
|
Return processed and validated server statistics.
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
def get_library_stats(self):
|
||||||
|
server_libraries = self.get_server_children()
|
||||||
|
|
||||||
|
server_library_stats = []
|
||||||
|
|
||||||
|
if server_libraries['libraries_count'] != '0':
|
||||||
|
libraries_list = server_libraries['libraries_list']
|
||||||
|
|
||||||
|
for library in libraries_list:
|
||||||
|
library_type = library['type']
|
||||||
|
section_key = library['key']
|
||||||
|
library_list = self.get_library_children(library_type, section_key)
|
||||||
|
|
||||||
|
if library_list['library_count'] != '0':
|
||||||
|
library_stats = {'title': library['title'],
|
||||||
|
'thumb': library['thumb'],
|
||||||
|
'count': library_list['library_count'],
|
||||||
|
'count_type': library_list['count_type']
|
||||||
|
}
|
||||||
|
|
||||||
|
if library_type == 'show':
|
||||||
|
episode_list = self.get_library_children(library_type='episode', section_key=section_key)
|
||||||
|
episode_stats = {'episode_count': episode_list['library_count'],
|
||||||
|
'episode_count_type': 'All Episodes'
|
||||||
|
}
|
||||||
|
library_stats.update(episode_stats)
|
||||||
|
|
||||||
|
if library_type == 'artist':
|
||||||
|
album_list = self.get_library_children(library_type='album', section_key=section_key)
|
||||||
|
album_stats = {'album_count': album_list['library_count'],
|
||||||
|
'album_count_type': 'All Albums'
|
||||||
|
}
|
||||||
|
library_stats.update(album_stats)
|
||||||
|
|
||||||
|
server_library_stats.append({'type': library_type,
|
||||||
|
'rows': library_stats})
|
||||||
|
|
||||||
|
return server_library_stats
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Return image data as array.
|
Return image data as array.
|
||||||
Array contains the image content type and image binary
|
Array contains the image content type and image binary
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
PLEXPY_VERSION = "master"
|
PLEXPY_VERSION = "master"
|
||||||
PLEXPY_RELEASE_VERSION = "1.1.5"
|
PLEXPY_RELEASE_VERSION = "1.1.6"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# This file is part of PlexPy.
|
# This file is part of PlexPy.
|
||||||
#
|
#
|
||||||
# PlexPy is free software: you can redistribute it and/or modify
|
# PlexPy is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -66,7 +66,9 @@ class WebInterface(object):
|
||||||
def home(self):
|
def home(self):
|
||||||
config = {
|
config = {
|
||||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||||
"home_stats_type": plexpy.CONFIG.HOME_STATS_TYPE
|
"home_stats_type": plexpy.CONFIG.HOME_STATS_TYPE,
|
||||||
|
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
|
||||||
|
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
|
||||||
}
|
}
|
||||||
return serve_template(templatename="index.html", title="Home", config=config)
|
return serve_template(templatename="index.html", title="Home", config=config)
|
||||||
|
|
||||||
|
@ -119,12 +121,19 @@ class WebInterface(object):
|
||||||
return json.dumps(formats)
|
return json.dumps(formats)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def home_stats(self, time_range='30', stat_type='0', **kwargs):
|
def home_stats(self, time_range='30', stat_type='0', stat_count='5', **kwargs):
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
stats_data = data_factory.get_home_stats(time_range=time_range, stat_type=stat_type)
|
stats_data = data_factory.get_home_stats(time_range=time_range, stat_type=stat_type, stat_count=stat_count)
|
||||||
|
|
||||||
return serve_template(templatename="home_stats.html", title="Stats", data=stats_data)
|
return serve_template(templatename="home_stats.html", title="Stats", data=stats_data)
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def library_stats(self, **kwargs):
|
||||||
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
stats_data = pms_connect.get_library_stats()
|
||||||
|
|
||||||
|
return serve_template(templatename="library_stats.html", title="Library Stats", data=stats_data)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def history(self):
|
def history(self):
|
||||||
return serve_template(templatename="history.html", title="History")
|
return serve_template(templatename="history.html", title="History")
|
||||||
|
@ -453,6 +462,7 @@ class WebInterface(object):
|
||||||
"notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT,
|
"notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT,
|
||||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||||
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
|
||||||
|
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
|
||||||
"buffer_threshold": plexpy.CONFIG.BUFFER_THRESHOLD,
|
"buffer_threshold": plexpy.CONFIG.BUFFER_THRESHOLD,
|
||||||
"buffer_wait": plexpy.CONFIG.BUFFER_WAIT
|
"buffer_wait": plexpy.CONFIG.BUFFER_WAIT
|
||||||
}
|
}
|
||||||
|
@ -567,6 +577,9 @@ class WebInterface(object):
|
||||||
if 'rating_key' in kwargs:
|
if 'rating_key' in kwargs:
|
||||||
rating_key = kwargs.get('rating_key', "")
|
rating_key = kwargs.get('rating_key', "")
|
||||||
custom_where = [['rating_key', rating_key]]
|
custom_where = [['rating_key', rating_key]]
|
||||||
|
if 'parent_rating_key' in kwargs:
|
||||||
|
rating_key = kwargs.get('parent_rating_key', "")
|
||||||
|
custom_where = [['parent_rating_key', rating_key]]
|
||||||
if 'grandparent_rating_key' in kwargs:
|
if 'grandparent_rating_key' in kwargs:
|
||||||
rating_key = kwargs.get('grandparent_rating_key', "")
|
rating_key = kwargs.get('grandparent_rating_key', "")
|
||||||
custom_where = [['grandparent_rating_key', rating_key]]
|
custom_where = [['grandparent_rating_key', rating_key]]
|
||||||
|
@ -747,16 +760,19 @@ class WebInterface(object):
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def info(self, item_id=None, source=None, **kwargs):
|
def info(self, item_id=None, source=None, **kwargs):
|
||||||
|
metadata = None
|
||||||
|
|
||||||
if source == 'history':
|
if source == 'history':
|
||||||
data_factory = datafactory.DataFactory()
|
data_factory = datafactory.DataFactory()
|
||||||
result = data_factory.get_metadata_details(row_id=item_id)
|
metadata = data_factory.get_metadata_details(row_id=item_id)
|
||||||
else:
|
else:
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_metadata_details(rating_key=item_id)['metadata']
|
result = pms_connect.get_metadata_details(rating_key=item_id)
|
||||||
|
if result:
|
||||||
|
metadata = result['metadata']
|
||||||
|
|
||||||
if result:
|
if metadata:
|
||||||
return serve_template(templatename="info.html", data=result, title="Info")
|
return serve_template(templatename="info.html", data=metadata, title="Info")
|
||||||
else:
|
else:
|
||||||
logger.warn('Unable to retrieve data.')
|
logger.warn('Unable to retrieve data.')
|
||||||
return serve_template(templatename="info.html", data=None, title="Info")
|
return serve_template(templatename="info.html", data=None, title="Info")
|
||||||
|
@ -801,7 +817,19 @@ class WebInterface(object):
|
||||||
return serve_template(templatename="user_platform_stats.html", data=None, title="Platform Stats")
|
return serve_template(templatename="user_platform_stats.html", data=None, title="Platform Stats")
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_children(self, rating_key='', **kwargs):
|
def get_show_children(self, rating_key='', **kwargs):
|
||||||
|
|
||||||
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
|
result = pms_connect.get_show_children(rating_key)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
return serve_template(templatename="info_season_list.html", data=result, title="Season List")
|
||||||
|
else:
|
||||||
|
logger.warn('Unable to retrieve data.')
|
||||||
|
return serve_template(templatename="info_season_list.html", data=None, title="Season List")
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def get_season_children(self, rating_key='', **kwargs):
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_season_children(rating_key)
|
result = pms_connect.get_season_children(rating_key)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue