mirror of
https://github.com/Tautulli/Tautulli.git
synced 2024-11-23 22:10:17 -08:00
1006 lines
52 KiB
HTML
1006 lines
52 KiB
HTML
<%inherit file="base.html"/>
|
|
|
|
<%def name="headIncludes()">
|
|
<link href="${http_root}css/jquery.scrollbar.css" rel="stylesheet">
|
|
</%def>
|
|
|
|
<%def name="body()">
|
|
<% from plexpy import PLEX_SERVER_UP %>
|
|
<div class="container-fluid">
|
|
% for section in config['home_sections']:
|
|
% if section == 'current_activity':
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="padded-header" id="current-activity-header">
|
|
<h3><span id="sessions-xml">Activity</span>
|
|
<small>
|
|
<span id="currentActivityHeader" style="display: none;">
|
|
Sessions: <span id="currentActivityHeader-streams"></span> |
|
|
Bandwidth: <span id="currentActivityHeader-bandwidth"></span>
|
|
<span id="currentActivityHeader-bandwidth-tooltip" data-toggle="tooltip" title="Streaming Brain Estimate (Reserved Bandwidth)"><i class="fa fa-info-circle"></i></span>
|
|
</span>
|
|
</small>
|
|
</h3>
|
|
</div>
|
|
<div id="currentActivity">
|
|
% if PLEX_SERVER_UP:
|
|
<div class="text-muted" id="dashboard-checking-activity"><i class="fa fa-refresh fa-spin"></i> Checking for activity...</div>
|
|
% elif config['pms_is_cloud']:
|
|
<div id="dashboard-no-activity" class="text-muted">Plex Cloud server is sleeping.</div>
|
|
% elif not config['first_run_complete']:
|
|
<div id="dashboard-no-activity" class="text-muted">The Tautulli setup wizard has not been completed. Please click <a href="welcome">here</a> to go to the setup wizard.</div>
|
|
% else:
|
|
<div class="text-muted" id="dashboard-checking-activity"><i class="fa fa-refresh fa-spin"></i> Tautulli is connecting to the Plex server...</div>
|
|
% endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
% elif section == 'watch_stats':
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="home-padded-header padded-header">
|
|
<h3 class="pull-left">Watch Statistics</h3>
|
|
<div class="button-bar">
|
|
<div class="btn-group pull-left" data-toggle="buttons" id="watch-stats-toggles" style="margin-right: 3px">
|
|
<label class="btn btn-dark btn-filter">
|
|
<input type="radio" class="watched-stats-toggle" name="watched-stats-type" id="watched-stats-plays" value="plays" autocomplete="off"> Play Count
|
|
</label>
|
|
<label class="btn btn-dark btn-filter">
|
|
<input type="radio" class="watched-stats-toggle" name="watched-stats-type" id="watched-stats-duration" value="duration" autocomplete="off"> Play Duration
|
|
</label>
|
|
</div>
|
|
<div class="input-group pull-left" style="width: 1px; margin-right: 3px" id="watched-stats-days-selection">
|
|
<span class="input-group-addon btn-dark inactive">Last</span>
|
|
<input type="number" class="form-control number-input" name="watched-stats-days" id="watched-stats-days" value="30" min="1" data-default="30" data-toggle="tooltip" title="Min: 1 day" />
|
|
<span class="input-group-addon btn-dark inactive">days</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div id="home-stats" class="home-platforms">
|
|
<div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
|
|
<br>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
% elif section == 'library_stats':
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="home-padded-header padded-header" id="library-statistics-header">
|
|
<h3 class="pull-left">Library Statistics</h3>
|
|
<div class="button-bar">
|
|
<span class="btn btn-dark active" style="cursor: default">${config['pms_name']}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<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>
|
|
% elif section == 'recently_added':
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="home-padded-header padded-header">
|
|
<h3 class="pull-left"><span id="recently-added-xml">Recently Added</span></h3>
|
|
<ul class="nav nav-header nav-dashboard pull-right" style="margin-top: -3px;">
|
|
<li>
|
|
<a href="#" id="recently-added-page-left" class="paginate-added btn-gray disabled" data-id="-1"><i class="fa fa-lg fa-chevron-left"></i></a>
|
|
</li>
|
|
<li>
|
|
<a href="#" id="recently-added-page-right" class="paginate-added btn-gray disabled" data-id="+1"><i class="fa fa-lg fa-chevron-right"></i></a>
|
|
</li>
|
|
</ul>
|
|
<div class="button-bar">
|
|
<div class="btn-group pull-left" data-toggle="buttons" id="recently-added-toggles" style="margin-right: 3px">
|
|
<label class="btn btn-dark btn-filter" id="recently-added-label-all">
|
|
<input type="radio" name="recently-added-toggle" id="recently-added-toggle-all" value="all" autocomplete="off"> All
|
|
</label>
|
|
<label class="btn btn-dark btn-filter" id="recently-added-label-movies">
|
|
<input type="radio" name="recently-added-toggle" id="recently-added-toggle-movie" value="movie" autocomplete="off"> Movies
|
|
</label>
|
|
<label class="btn btn-dark btn-filter" id="recently-added-label-tv">
|
|
<input type="radio" name="recently-added-toggle" id="recently-added-toggle-show" value="show" autocomplete="off"> TV Shows
|
|
</label>
|
|
<label class="btn btn-dark btn-filter" id="recently-added-label-music">
|
|
<input type="radio" name="recently-added-toggle" id="recently-added-toggle-artist" value="artist" autocomplete="off"> Music
|
|
</label>
|
|
<label class="btn btn-dark btn-filter" id="recently-added-label-other_video">
|
|
<input type="radio" name="recently-added-toggle" id="recently-added-toggle-other_video" value="other_video" autocomplete="off"> Videos
|
|
</label>
|
|
</div>
|
|
<div class="input-group pull-left" style="width: 1px;" id="recently-added-count-selection">
|
|
<input type="number" class="form-control number-input" name="recently-added-count" id="recently-added-count" value="50" min="1" max="50" data-default="50" data-toggle="tooltip" title="Min: 1 item<br>Max: 50 items" />
|
|
<span class="input-group-addon btn-dark inactive">items</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div id="recentlyAdded" style="margin-right: -15px;">
|
|
% if PLEX_SERVER_UP:
|
|
<div id="dashboard-checking-recently-added" class="text-muted"><i class="fa fa-refresh fa-spin"></i> Looking for new items...</div>
|
|
% elif config['pms_is_cloud']:
|
|
<div class="text-muted">Plex Cloud server is sleeping.</div>
|
|
% else:
|
|
<div id="dashboard-no-recently-added" class="text-muted"><i class="fa fa-refresh fa-spin"></i> Tautulli is connecting to your Plex server...</div>
|
|
% endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
% endfor
|
|
</div>
|
|
</%def>
|
|
|
|
<%def name="modalIncludes()">
|
|
|
|
% if _session['user_group'] == 'admin' and config['update_show_changelog']:
|
|
<% from plexpy.common import RELEASE %>
|
|
<div id="changelog-modal" class="modal fade wide" tabindex="-1" role="dialog" aria-labelledby="changelog-modal">
|
|
<div class="modal-dialog" role="document">
|
|
<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">Tautulli Updated to <strong>${RELEASE}</strong></h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" data-target="#donate-modal" data-toggle="modal" style="float: left;"><i class="fa fa-fw fa-heart"></i> Donate</button>
|
|
<input type="button" class="btn btn-bright" data-dismiss="modal" value="Close">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
% if _session['user_group'] == 'admin':
|
|
<div id="terminate-session-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="terminate-session-modal">
|
|
<div class="modal-dialog" role="document">
|
|
<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">Terminate Stream</h4>
|
|
</div>
|
|
<div class="modal-body" style="text-align: center;">
|
|
<p>Are you sure you want to terminate this stream?</p>
|
|
<p>
|
|
<strong>
|
|
<span id="terminate-user"></span><br />
|
|
<span id="terminate-title"></span><br />
|
|
<span id="terminate-subtitle"></span>
|
|
</strong>
|
|
</p>
|
|
<br />
|
|
<label for="terminate-message">Terminate Message</label>
|
|
<div class="row">
|
|
<div class="col-md-8" style="float: none; margin: 0 auto;">
|
|
<input type="text" class="form-control" id="terminate-message" name="terminate-message" value="" placeholder="The server owner has ended the stream." style="text-align: center;">
|
|
</div>
|
|
</div>
|
|
</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-terminate-session">Terminate</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal fade wide" id="raw-stream-info-modal" tabindex="-1" role="dialog" aria-labelledby="raw-stream-info-modal">
|
|
<div class="modal-dialog" role="document">
|
|
<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">Raw Stream Info: <strong><span id="raw-stream-info-title"></span> (<span id="raw-stream-info-user"></span>)</strong></h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<pre id="raw-stream-info"></pre>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<input type="button" class="btn btn-bright" data-dismiss="modal" value="Close">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
|
|
</div>
|
|
|
|
</%def>
|
|
|
|
<%def name="javascriptIncludes()">
|
|
<script src="${http_root}js/jquery.scrollbar.min.js"></script>
|
|
<script src="${http_root}js/jquery.mousewheel.min.js"></script>
|
|
<script>
|
|
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;
|
|
}
|
|
});
|
|
|
|
function lockScroll(elem) {
|
|
$(elem).each(function (i, instance) {
|
|
var childHeight = $(instance).children('.scoller-content').height();
|
|
var height = $(instance).height();
|
|
var scrollHeight = $(instance).get(0).scrollHeight;
|
|
|
|
if (childHeight > height) {
|
|
$(instance).on('mousewheel', function(e, d) {
|
|
if(($(instance).scrollTop() >= (scrollHeight - height)) && d < 0 || ($(instance).scrollTop() <= 0) && d > 0) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
% if _session['user_group'] == 'admin':
|
|
var msg_settings = ' Check the <a href="logs">logs</a> and verify your server connection in the <a href="settings#tab_tabs-plex_media_server">settings</a>.';
|
|
% else:
|
|
var msg_settings = '';
|
|
% endif
|
|
|
|
var error_msg = 'There was an error communicating with your Plex Server.' + msg_settings;
|
|
|
|
% if 'current_activity' in config['home_sections'] or 'recently_added' in config['home_sections']:
|
|
var server_status;
|
|
server_status = setInterval(function() {
|
|
$.getJSON('server_status', function (data) {
|
|
if (data.connected === true) {
|
|
clearInterval(server_status);
|
|
% if 'current_activity' in config['home_sections']:
|
|
$('#currentActivity').html('<div id="dashboard-checking-activity" class="text-muted"><i class="fa fa-refresh fa-spin"></i> Checking for activity...</div>');
|
|
activityConnected();
|
|
% endif
|
|
% if 'recently_added' in config['home_sections']:
|
|
$('#recentlyAdded').html('<div id="dashboard-checking-recently-added" class="text-muted"><i class="fa fa-refresh fa-spin"></i> Looking for new items...</div>');
|
|
recentlyAddedConnected();
|
|
% endif
|
|
} else if (data.connected === false) {
|
|
clearInterval(server_status);
|
|
% if 'current_activity' in config['home_sections']:
|
|
$('#currentActivity').html('<div id="dashboard-no-activity" class="text-muted">' + error_msg + '</div>');
|
|
% endif
|
|
% if 'recently_added' in config['home_sections']:
|
|
$('#recentlyAdded').html('<div id="dashboard-no-recently-added" class="text-muted">' + error_msg + '</div>');
|
|
% endif
|
|
}
|
|
});
|
|
}, 1000);
|
|
% endif
|
|
</script>
|
|
% if 'current_activity' in config['home_sections']:
|
|
<script>
|
|
var defaultHandler = {
|
|
get: function(target, name) {
|
|
return target.hasOwnProperty(name) ? target[name] : 'Unknown';
|
|
}
|
|
};
|
|
|
|
var create_instances = [];
|
|
var activity_ready = true;
|
|
|
|
$('#currentActivityHeader-bandwidth-tooltip').tooltip({ container: 'body', placement: 'right', delay: 50 });
|
|
|
|
function getCurrentActivity() {
|
|
activity_ready = false;
|
|
|
|
$.ajax({
|
|
url: 'get_activity',
|
|
type: 'GET',
|
|
cache: false,
|
|
async: true,
|
|
error: function (xhr, status, error) {
|
|
console.log(status + ': ' + error);
|
|
activity_ready = true;
|
|
},
|
|
complete: function (xhr, status) {
|
|
$('#dashboard-checking-activity').remove();
|
|
|
|
var current_activity;
|
|
try {
|
|
current_activity = $.parseJSON(xhr.responseText);
|
|
} catch (e) {
|
|
console.log(status + ': ' + e);
|
|
current_activity = null;
|
|
}
|
|
|
|
if (!(current_activity)) {
|
|
$('#currentActivityHeader').hide();
|
|
$('#currentActivity').html('<div id="dashboard-no-activity" class="text-muted">' + error_msg + '</div>');
|
|
return
|
|
}
|
|
|
|
var stream_count = parseInt(current_activity.stream_count);
|
|
var sessions = current_activity.sessions;
|
|
|
|
if (stream_count) {
|
|
$('#dashboard-no-activity').remove();
|
|
|
|
// Update the header stream counts
|
|
var sc_dp = current_activity.stream_count_direct_play,
|
|
sc_ds = current_activity.stream_count_direct_stream,
|
|
sc_tc = current_activity.stream_count_transcode,
|
|
total_bw = current_activity.total_bandwidth,
|
|
lan_bw = current_activity.lan_bandwidth,
|
|
wan_bw = current_activity.wan_bandwidth;
|
|
var streams_header = stream_count + ' stream' + (stream_count > 1 ? 's' : '') + ' (';
|
|
if (sc_dp) {
|
|
streams_header += sc_dp + ' direct play' + (sc_dp > 1 ? 's' : '') + ', ';
|
|
}
|
|
if (sc_ds) {
|
|
streams_header += sc_ds + ' direct stream' + (sc_ds > 1 ? 's' : '') + ', ';
|
|
}
|
|
if (sc_tc) {
|
|
streams_header += sc_tc + ' transcode' + (sc_tc > 1 ? 's' : '') + ', ';
|
|
}
|
|
streams_header = streams_header.replace(/, $/, '') + ')';
|
|
$('#currentActivityHeader-streams').text(streams_header);
|
|
|
|
var bandwidth_header = ((total_bw > 1000000) ? ((total_bw / 1000000).toFixed(1) + ' Gbps') : ((total_bw > 1000) ? ((total_bw / 1000).toFixed(1) + ' Mbps') : (total_bw + ' kbps')));
|
|
var lan_wan_bandwidth_header = '';
|
|
if (lan_bw) {
|
|
lan_wan_bandwidth_header += 'LAN: ' + ((lan_bw > 1000000) ? ((lan_bw / 1000000).toFixed(1) + ' Gbps') : ((lan_bw > 1000) ? ((lan_bw / 1000).toFixed(1) + ' Mbps') : (lan_bw + ' kbps'))) + ', ';
|
|
}
|
|
if (wan_bw) {
|
|
lan_wan_bandwidth_header += 'WAN: ' + ((wan_bw > 1000000) ? ((wan_bw / 1000000).toFixed(1) + ' Gbps') : ((wan_bw > 1000) ? ((wan_bw / 1000).toFixed(1) + ' Mbps') : (wan_bw + ' kbps'))) + ', ';
|
|
}
|
|
if (lan_wan_bandwidth_header) {
|
|
bandwidth_header += ' (' + lan_wan_bandwidth_header.replace(/, $/, '') + ')';
|
|
}
|
|
$('#currentActivityHeader-bandwidth').text(bandwidth_header);
|
|
|
|
$('#currentActivityHeader').show();
|
|
|
|
sessions.forEach(function (session) {
|
|
var s = (typeof Proxy === "function") ? new Proxy(session, defaultHandler) : session;
|
|
var key = s.session_key;
|
|
var session_id = s.session_id;
|
|
var instance = $('#activity-instance-' + key);
|
|
|
|
// Create a new instance if it doesn't exist or recreate the entire instance
|
|
// if the rating key changed (for movies or episodes) of guid changed (for live tv) with the same session key
|
|
if (!(instance.length) ||
|
|
(s.media_type !== 'track' && s.rating_key !== instance.data('rating_key').toString()) ||
|
|
(s.live === 1 && s.guid !== instance.data('guid'))) {
|
|
create_instances.push(key);
|
|
getActivityInstance(key);
|
|
return;
|
|
}
|
|
|
|
// Update play state icon
|
|
var state_icon = '';
|
|
switch (s.state) {
|
|
case 'playing':
|
|
state_icon = '<i class="fa fa-fw fa-play"></i> ';
|
|
break;
|
|
case 'paused':
|
|
state_icon = '<i class="fa fa-fw fa-pause"></i> ';
|
|
break;
|
|
case 'buffering':
|
|
state_icon = '<i class="fa fa-fw fa-spinner"></i> ';
|
|
break;
|
|
case 'error':
|
|
state_icon = '<i class="fa fa-fw fa-exclamation-triangle"></i> ';
|
|
break;
|
|
default:
|
|
state_icon = '<i class="fa fa-fw fa-question-circle"></i> ';
|
|
}
|
|
$('#play-state-' + key).html(state_icon).attr('title', capitalizeFirstLetter(s.state));
|
|
|
|
// Switching tracks can be under the same session key, so need to update the info.
|
|
if (s.media_type === 'track') {
|
|
// Update if artist changed
|
|
if (s.grandparent_rating_key !== instance.data('grandparent_rating_key').toString()) {
|
|
$('#background-' + key).css('background-image', 'url(' + page('pms_image_proxy', s.art, s.rating_key, 500, 280, 40, '282828', 3, 'art', true) + ')');
|
|
$('#metadata-grandparent_title-' + key)
|
|
.attr('href', page('info', s.grandparent_rating_key))
|
|
.attr('title', s.original_title || s.grandparent_title)
|
|
.text(s.original_title || s.grandparent_title);
|
|
}
|
|
// Update cover if album changed
|
|
if (s.parent_rating_key !== instance.data('parent_rating_key').toString()) {
|
|
$('#poster-' + key).css('background-image', 'url(' + page('pms_image_proxy', s.parent_thumb, s.parent_rating_key, 300, 300, null, null, null, 'poster', true) + ')');
|
|
$('#poster-' + key + '-bg').css('background-image', 'url(' + page('pms_image_proxy', s.parent_thumb, s.parent_rating_key, 300, 300, 60, '282828', 3, 'poster', true) + ')');
|
|
$('#poster-url-' + key)
|
|
.attr('href', page('info', s.parent_rating_key))
|
|
.attr('title', s.parent_title);
|
|
$('#metadata-parent_title-' + key)
|
|
.attr('href', page('info', s.parent_rating_key))
|
|
.attr('title', s.parent_title)
|
|
.text(s.parent_title);
|
|
}
|
|
// Update cover if track changed
|
|
if (s.rating_key !== instance.data('rating_key').toString()) {
|
|
$('#metadata-grandparent_title-' + key)
|
|
.attr('href', page('info', s.grandparent_rating_key))
|
|
.attr('title', s.original_title || s.grandparent_title)
|
|
.text(s.original_title || s.grandparent_title);
|
|
$('#metadata-title-' + key)
|
|
.attr('href', page('info', s.rating_key))
|
|
.attr('title', s.title)
|
|
.text(s.title);
|
|
}
|
|
}
|
|
|
|
// Update the transcode state
|
|
var transcode_decision = '';
|
|
if (s.transcode_decision === 'transcode') {
|
|
var throttled = (s.transcode_throttled === 1) ? ' (Throttled)' : ' (Speed: ' + s.transcode_speed + ')';
|
|
transcode_decision = 'Transcode' + throttled;
|
|
} else if (s.transcode_decision === 'copy') {
|
|
transcode_decision = 'Direct Stream';
|
|
} else {
|
|
transcode_decision = 'Direct Play';
|
|
}
|
|
$('#transcode_decision-' + key).html(transcode_decision);
|
|
|
|
var transcode_container = '';
|
|
if (s.stream_container_decision === 'transcode') {
|
|
transcode_container = 'Converting (' + s.container.toUpperCase() + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_container.toUpperCase() + ')';
|
|
} else {
|
|
transcode_container = 'Direct Play (' + s.stream_container.toUpperCase() + ')';
|
|
}
|
|
$('#transcode_container-' + key).html(transcode_container);
|
|
|
|
var video_decision = '';
|
|
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.stream_video_decision) {
|
|
var v_bd = (s.video_dynamic_range !== 'SDR') ? ' ' + s.video_dynamic_range : '';
|
|
var sv_bd = (s.stream_video_dynamic_range !== 'SDR' || v_bd) ? ' ' + s.stream_video_dynamic_range : '';
|
|
var v_res= '';
|
|
switch (s.video_resolution.toLowerCase()) {
|
|
case 'sd':
|
|
v_res = 'SD';
|
|
break;
|
|
case '4k':
|
|
v_res = '4k';
|
|
break;
|
|
default:
|
|
v_res = s.video_full_resolution;
|
|
}
|
|
var sv_res = '';
|
|
switch (s.stream_video_resolution.toLowerCase()) {
|
|
case 'sd':
|
|
sv_res = 'SD';
|
|
break;
|
|
case '4k':
|
|
sv_res = '4k';
|
|
break;
|
|
default:
|
|
sv_res = s.stream_video_full_resolution;
|
|
}
|
|
if (s.stream_video_decision === 'transcode') {
|
|
var hw_d = (s.transcode_hw_decoding === 1) ? ' (HW)' : '';
|
|
var hw_e = (s.transcode_hw_encoding === 1) ? ' (HW)' : '';
|
|
video_decision = 'Transcode (' + s.video_codec.toUpperCase() + hw_d + ' ' + v_res + v_bd + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_video_codec.toUpperCase() + hw_e + ' ' + sv_res + sv_bd + ')';
|
|
} else if (s.stream_video_decision === 'copy') {
|
|
video_decision = 'Direct Stream (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + sv_bd + ')';
|
|
} else {
|
|
video_decision = 'Direct Play (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + sv_bd + ')';
|
|
}
|
|
} else if (s.media_type === 'photo') {
|
|
video_decision = 'Direct Play (' + s.width + 'x' + s.height + ')';
|
|
}
|
|
$('#video_decision-' + key).html(video_decision);
|
|
|
|
var audio_decision = '';
|
|
if (['movie', 'episode', 'clip', 'track'].indexOf(s.media_type) > -1 && s.stream_audio_decision) {
|
|
var audio_language = (s.media_type !== 'track') ? (s.audio_language || 'Unknown') + ' - ' : '';
|
|
var a_codec = (s.audio_codec === 'truehd') ? 'TrueHD' : s.audio_codec.toUpperCase();
|
|
var sa_codec = (s.stream_audio_codec === 'truehd') ? 'TrueHD' : s.stream_audio_codec.toUpperCase();
|
|
if (s.stream_audio_decision === 'transcode') {
|
|
audio_decision = 'Transcode (' + audio_language + a_codec + ' ' + capitalizeFirstLetter(s.audio_channel_layout.split('(')[0]) + ' <i class="fa fa-long-arrow-right"></i> ' + sa_codec + ' ' + capitalizeFirstLetter(s.stream_audio_channel_layout.split('(')[0]) + ')';
|
|
} else if (s.stream_audio_decision === 'copy') {
|
|
audio_decision = 'Direct Stream (' + audio_language + sa_codec + ' ' + capitalizeFirstLetter(s.stream_audio_channel_layout.split('(')[0]) + ')';
|
|
} else {
|
|
audio_decision = 'Direct Play (' + audio_language + sa_codec + ' ' + capitalizeFirstLetter(s.stream_audio_channel_layout.split('(')[0]) + ')';
|
|
}
|
|
}
|
|
$('#audio_decision-' + key).html(audio_decision);
|
|
|
|
var subtitle_decision = 'None';
|
|
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.subtitles === 1) {
|
|
var subtitle_codec = (s.stream_subtitle_codec && s.stream_subtitle_transient) ? 'None' : s.subtitle_codec.toUpperCase();
|
|
if (s.stream_subtitle_decision === 'transcode') {
|
|
subtitle_decision = 'Transcode ('+ (s.subtitle_language || 'Unknown')+ ' - ' + subtitle_codec + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_subtitle_codec.toUpperCase() + ')';
|
|
} else if (s.stream_subtitle_decision === 'copy') {
|
|
subtitle_decision = 'Direct Stream ('+ (s.subtitle_language || 'Unknown')+ ' - ' + subtitle_codec + ')';
|
|
} else if (s.stream_subtitle_decision === 'burn') {
|
|
subtitle_decision = 'Burn ('+ (s.subtitle_language || 'Unknown')+ ' - ' + subtitle_codec + ')';
|
|
} else {
|
|
subtitle_decision = 'Direct Play ('+ (s.subtitle_language || 'Unknown')+ ' - ' + ((s.synced_version === '1') ? subtitle_codec : s.stream_subtitle_codec.toUpperCase()) + ')';
|
|
}
|
|
}
|
|
$('#subtitle_decision-' + key).html(subtitle_decision);
|
|
|
|
// Update the stream quality profile and bandwidth
|
|
if (s.media_type !== 'photo' && s.quality_profile !== 'Unknown') {
|
|
var br = parseInt(s.stream_bitrate) || '';
|
|
if (br) {
|
|
if (br > 1000) {
|
|
br = ' (' + (br / 1000).toFixed(1) + ' Mbps)';
|
|
} else {
|
|
br = ' (' + br + ' kbps)';
|
|
}
|
|
}
|
|
$('#stream_quality-' + key).html(s.quality_profile + br);
|
|
} else {
|
|
$('#stream_quality-' + key).html(s.quality_profile);
|
|
}
|
|
$('#optimized_version-' + key).html(s.optimized_version_profile + ' (' + s.optimized_version_title + ')');
|
|
$('#synced_quality_profile-' + key).html(s.synced_quality_profile);
|
|
|
|
$('#location-' + key).html(s.location.toUpperCase());
|
|
|
|
if (s.media_type !== 'photo' && s.bandwidth !== 'Unknown') {
|
|
var bw = parseInt(s.bandwidth) || 0;
|
|
if (bw > 1000000) {
|
|
bw = (bw / 1000000).toFixed(1) + ' Gbps';
|
|
} else if (bw > 1000) {
|
|
bw = (bw / 1000).toFixed(1) + ' Mbps';
|
|
} else {
|
|
bw = bw + ' kbps'
|
|
}
|
|
$('#stream-bandwidth-' + key).html(bw);
|
|
}
|
|
|
|
// Update the stream progress times
|
|
$('#stream-eta-' + key).html(moment().add(parseInt(s.duration) - parseInt(s.view_offset), 'milliseconds').format(time_format));
|
|
$('#stream-duration-' + key).html(millisecondsToMinutes(parseInt(s.stream_duration), false));
|
|
var stream_view_offset = $('#stream-view-offset-' + key);
|
|
stream_view_offset.data('state', s.state);
|
|
if (stream_view_offset.data('last_view_offset') !== s.view_offset) {
|
|
stream_view_offset.data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
|
}
|
|
|
|
// Update the progress bars
|
|
var duration = parseInt(s.duration);
|
|
var transcode_progress = duration ? Math.round(s.transcode_max_offset_available * 1000 / duration * 100) : s.transcode_progress;
|
|
$('#buffer-bar-' + key).css({width: parseInt(transcode_progress) + '%'}).html(transcode_progress + '%')
|
|
.attr('data-original-title', 'Transcoder Progress ' + transcode_progress + '%');
|
|
if (s.live !== 1) {
|
|
var progress_bar = $('#progress-bar-' + key);
|
|
progress_bar.data('state', s.state);
|
|
if (progress_bar.data('last_view_offset') !== s.view_offset) {
|
|
progress_bar.data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
|
}
|
|
}
|
|
|
|
// Add temporary class so we know which instances are still active
|
|
instance.addClass('updated-temp');
|
|
});
|
|
|
|
// Remove finished instances
|
|
$('div[id^=activity-instance-]').each(function (i, instance) {
|
|
if ($(instance).hasClass('updated-temp')) {
|
|
$(instance).removeClass('updated-temp');
|
|
} else {
|
|
$(instance).find('[data-toggle=tooltip]').tooltip('destroy');
|
|
$(instance).find('[data-toggle=popover]').popover('destroy');
|
|
$(instance).remove();
|
|
}
|
|
});
|
|
|
|
} else {
|
|
$('#currentActivityHeader').hide();
|
|
$('#currentActivity').html('<div id="dashboard-no-activity" class="text-muted">Nothing is currently being played.</div>');
|
|
}
|
|
|
|
activity_ready = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getActivityInstance(session_key) {
|
|
$.ajax({
|
|
url: 'get_current_activity_instance',
|
|
type: 'GET',
|
|
cache: false,
|
|
async: true,
|
|
data: {
|
|
session_key: session_key
|
|
},
|
|
complete: function(xhr, status) {
|
|
var instance = $('#activity-instance-' + session_key);
|
|
|
|
if (instance.length) {
|
|
instance.replaceWith(xhr.responseText);
|
|
} else {
|
|
$('#currentActivity').append(xhr.responseText);
|
|
}
|
|
|
|
$('#activity-instance-' + session_key + ' .dashboard-activity-info-scroller').scrollbar();
|
|
$('#activity-instance-' + session_key + ' [data-toggle=tooltip]').tooltip({ container: 'body', placement: 'right', delay: 50 });
|
|
$('#activity-instance-' + session_key + ' [data-toggle=popover]').popover({
|
|
html: true,
|
|
sanitize: false,
|
|
container: 'body',
|
|
trigger: 'hover',
|
|
placement: 'right',
|
|
delay: 50,
|
|
template: '<div class="popover channel-thumbnail-popover" role="tooltip"><div class="arrow" style="top: 50%;"></div><div class="popover-content"></div></div>',
|
|
content: function () {
|
|
return '<div class="channel-thumbnail" style="background-image: url(' + $(this).data('img') + ');" />';
|
|
}
|
|
});
|
|
$('#terminate-button-' + session_key).tooltip('destroy').tooltip({ container: 'body', placement: 'left', delay: 50 });
|
|
lockScroll('#activity-instance-' + session_key + ' .dashboard-activity-info-scroller');
|
|
|
|
var index = create_instances.indexOf(session_key);
|
|
if (index > -1) {
|
|
create_instances.splice(index, 1);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function activityConnected() {
|
|
getCurrentActivity();
|
|
setInterval(function () {
|
|
if (!(create_instances.length) && activity_ready) {
|
|
getCurrentActivity();
|
|
}
|
|
}, ${config['home_refresh_interval'] * 1000});
|
|
|
|
setInterval(function(){
|
|
$('.progress_time_offset').each(function () {
|
|
if ($(this).data('state') === 'playing' && $(this).data('view_offset') >= 0) {
|
|
var view_offset = parseInt($(this).data('view_offset'));
|
|
var stream_duration = parseInt($(this).data('stream_duration'));
|
|
var timestamp = millisecondsToMinutes(Math.min(view_offset, stream_duration), false);
|
|
$(this).html(timestamp).data('view_offset', Math.min(view_offset + 1000, stream_duration))
|
|
}
|
|
});
|
|
$('.progress-bar').each(function () {
|
|
if ($(this).data('state') === 'playing' && $(this).data('view_offset') >= 0) {
|
|
var view_offset = parseInt($(this).data('view_offset'));
|
|
var stream_duration = parseInt($(this).data('stream_duration'));
|
|
var progress_percent = Math.floor(view_offset / stream_duration * 100);
|
|
progress_percent = (progress_percent >= 0) ? Math.min(progress_percent, 100) : 100;
|
|
$(this).css({width: progress_percent + '%'}).html(progress_percent + '%')
|
|
.attr('data-original-title', 'Stream Progress ' + progress_percent + '%')
|
|
.data('view_offset', Math.min(view_offset + 1000, stream_duration));
|
|
}
|
|
});
|
|
}, 1000);
|
|
}
|
|
|
|
$('#currentActivity').on('click', '.external_ip-modal', function () {
|
|
$.get('get_ip_address_details', {
|
|
ip_address: $(this).data('ip'),
|
|
location: $(this).data('location'),
|
|
secure: $(this).data('secure'),
|
|
relayed: $(this).data('relayed')
|
|
}).then(function (jqXHR) {
|
|
$("#ip-info-modal").html(jqXHR);
|
|
});
|
|
});
|
|
|
|
$('#currentActivity').on('click', '.raw-stream-info-modal', function () {
|
|
$.ajax({
|
|
url: 'get_activity',
|
|
type: 'GET',
|
|
cache: false,
|
|
async: true,
|
|
data: {
|
|
session_key: $(this).data('key')
|
|
},
|
|
error: function (xhr, status, error) {
|
|
console.log(status + ': ' + error);
|
|
},
|
|
complete: function (xhr, status) {
|
|
var session = $.parseJSON(xhr.responseText);
|
|
$('#raw-stream-info-title').text(session.full_title);
|
|
$('#raw-stream-info-user').text(session.friendly_name);
|
|
$('#raw-stream-info').text(JSON.stringify(session, Object.keys(session).sort(), 4));
|
|
}
|
|
});
|
|
});
|
|
|
|
% if _session['user_group'] == 'admin':
|
|
// Terminate session
|
|
$('#currentActivity').on('click', '.dashboard-activity-terminate-session', function (e) {
|
|
e.preventDefault();
|
|
var session_id = $(this).data('id');
|
|
var key = $(this).data('key');
|
|
var instance = $('#activity-instance-' + key);
|
|
|
|
$('#terminate-user').text(instance.find('.dashboard-activity-metadata-user').text());
|
|
$('#terminate-title').text(instance.find('.dashboard-activity-metadata-title').text());
|
|
$('#terminate-subtitle').text(instance.find('.dashboard-activity-metadata-subtitle').text());
|
|
|
|
$('#terminate-session-modal').modal();
|
|
$('#terminate-session-modal').one('click', '#confirm-terminate-session', function () {
|
|
var message = $('#terminate-message').val();
|
|
|
|
showMsg('Terminating session', true);
|
|
|
|
$.ajax({
|
|
url: 'terminate_session',
|
|
data: {
|
|
session_key: key,
|
|
session_id: session_id,
|
|
message: message
|
|
},
|
|
async: true,
|
|
success: function (data) {
|
|
if (data.result === 'success') {
|
|
setTimeout(function() {
|
|
getCurrentActivity();
|
|
showMsg('<i class="fa fa-check"></i> ' + data.message, false, true, 5000);
|
|
}, 2500);
|
|
} else {
|
|
showMsg('<i class="fa fa-exclamation-circle"></i> ' + data.message, false, true, 5000, true);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
$('#sessions-xml').on('tripleclick', function () {
|
|
openPlexXML('/status/sessions');
|
|
});
|
|
% endif
|
|
</script>
|
|
% endif
|
|
% if 'watch_stats' in config['home_sections'] or 'library_stats' in config['home_sections']:
|
|
<script>
|
|
function statsCardCallback() {
|
|
$('.dashboard-stats-instance .dashboard-stats-info-scroller').scrollbar();
|
|
loadAllBlurHash();
|
|
|
|
function changeImages(elem) {
|
|
var stat_id = $(elem).data('stat_id');
|
|
var art = $(elem).data('art');
|
|
var thumb = $(elem).data('thumb');
|
|
var user_id = $(elem).data('user_id');
|
|
var library_type = $(elem).data('library-type');
|
|
var user_thumb = $(elem).data('user_thumb');
|
|
var rating_key = $(elem).data('rating_key');
|
|
var grandparent_rating_key = $(elem).data('grandparent_rating_key');
|
|
var guid = $(elem).data('guid');
|
|
var live = $(elem).data('live');
|
|
var library_art = $(elem).data('library_art');
|
|
var library_thumb = $(elem).data('library_thumb');
|
|
var [height, fallback_poster, fallback_art] = [450, 'poster', 'art'];
|
|
if ($.inArray(stat_id, ['top_music', 'popular_music']) > -1) {
|
|
[height, fallback_poster, fallback_art] = [300, 'cover', 'art'];
|
|
} else if (live) {
|
|
[height, fallback_poster, fallback_art] = [450, 'poster-live', 'art-live'];
|
|
}
|
|
var href = '#';
|
|
|
|
if (stat_id === 'most_concurrent') {
|
|
return
|
|
} else if (stat_id === 'top_libraries') {
|
|
$('#stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art || library_art, null, 500, 280, 40, '282828', 3, fallback_art) + ')');
|
|
$('#stats-thumb-' + stat_id).removeClass(function (index, className) {
|
|
return (className.match (/(^|\s)svg-icon library-\S+/g) || []).join(' ')});
|
|
if (library_thumb.startsWith('http')) {
|
|
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', library_thumb, null, 100, 100, null, null, null, 'cover') + ')');
|
|
} else {
|
|
$('#stats-thumb-' + stat_id).css('background-image', '')
|
|
.addClass('svg-icon library-' + library_type);
|
|
}
|
|
} else if (stat_id === 'top_users') {
|
|
loadBlurHash($('#stats-background-' + stat_id), page('pms_image_proxy', user_thumb || 'interfaces/default/images/gravatar-default.png', null, 100, 100, 40, '282828', 0, 'user'));
|
|
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', user_thumb || 'interfaces/default/images/gravatar-default.png', null, 100, 100, null, null, null, 'user') + ')');
|
|
if (user_id) {
|
|
href = page('user', user_id);
|
|
}
|
|
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('user'));
|
|
} else if (stat_id === 'top_platforms') {
|
|
$('#stats-thumb-' + stat_id).removeClass(function (index, className) {
|
|
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
|
|
}).addClass('platform-' + $(elem).data('platform'));
|
|
$('#stats-background-' + stat_id).removeClass(function (index, className) {
|
|
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
|
|
}).addClass('platform-' + $(elem).data('platform') + '-rgba');
|
|
} else {
|
|
if (rating_key) {
|
|
if (live) {
|
|
href = page('info', rating_key, guid, true, live);
|
|
} else {
|
|
href = page('info', rating_key);
|
|
}
|
|
}
|
|
var img_rating_key = grandparent_rating_key || rating_key;
|
|
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('title'));
|
|
$('#stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art, img_rating_key, 500, 280, 40, '282828', 3, fallback_art) + ')');
|
|
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', thumb, img_rating_key, 300, height, null, null, null, fallback_poster) + ')');
|
|
$('#stats-thumb-' + stat_id + '-bg').css('background-image', 'url(' + page('pms_image_proxy', thumb, img_rating_key, 300, height, 60, '282828', 3, fallback_poster) + ')');
|
|
$('#library-stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art || library_art, img_rating_key, 500, 280, 40, '282828', 3, library_art || fallback_art) + ')');
|
|
if (thumb.startsWith('http')) {
|
|
$('#library-stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', thumb, img_rating_key, 300, 300, null, null, null, 'cover') + ')')
|
|
.removeClass('svg-icon library-' + stat_id);
|
|
} else {
|
|
$('#library-stats-thumb-' + stat_id).css('background-image', '')
|
|
.addClass('svg-icon library-' + stat_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
$('.dashboard-stats-info-item').mouseenter(function () {
|
|
changeImages(this);
|
|
if ($(this).data('stat_id') === 'last_watched') {
|
|
var friendly_name = $(this).data('friendly_name');
|
|
var last_watch = moment($(this).data('last_watch'), 'X').format(date_format);
|
|
$('#last-watched-header-info').html(friendly_name);
|
|
} else if ($(this).data('stat_id') === 'most_concurrent') {
|
|
var started = moment($(this).data('started'), 'X').format(date_format + ' ' + time_format);
|
|
$('#most-concurrent-header-info').html(started);
|
|
}
|
|
});
|
|
$('.dashboard-stats-instance').mouseleave(function () {
|
|
changeImages($(this).find('.dashboard-stats-info-item').first());
|
|
if ($(this).data('stat_id') === 'last_watched') {
|
|
$('#last-watched-header-info').text($(this).find('.dashboard-stats-info-item').first().data('friendly_name'));
|
|
} else if ($(this).data('stat_id') === 'most_concurrent') {
|
|
$('#most-concurrent-header-info').text('streams');
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
% endif
|
|
% if 'watch_stats' in config['home_sections']:
|
|
<script>
|
|
function getHomeStats(time_range, stats_type) {
|
|
showMsg("Loading watch statistics...", true, false, 0);
|
|
|
|
$.ajax({
|
|
url: 'home_stats',
|
|
type: 'GET',
|
|
cache: false,
|
|
async: true,
|
|
data: {
|
|
time_range: time_range,
|
|
stats_type: stats_type
|
|
},
|
|
complete: function (xhr, status) {
|
|
$("#home-stats").html(xhr.responseText);
|
|
$('#ajaxMsg').fadeOut();
|
|
lockScroll('#home-stats .dashboard-stats-info-scroller');
|
|
statsCardCallback();
|
|
}
|
|
});
|
|
}
|
|
|
|
var stats_type = getLocalStorage('home_stats_type', 'plays');
|
|
var time_range = getLocalStorage('home_stats_days', 30);
|
|
|
|
$('#watched-stats-' + stats_type).prop('checked', true);
|
|
$('#watched-stats-' + stats_type).closest('label').addClass('active');
|
|
$('#watched-stats-days').val(time_range);
|
|
|
|
getHomeStats(time_range, stats_type);
|
|
|
|
$('input[name=watched-stats-type]').change(function () {
|
|
stats_type = $(this).filter(':checked').val();
|
|
setLocalStorage('home_stats_type', stats_type);
|
|
getHomeStats(time_range, stats_type);
|
|
});
|
|
$('#watched-stats-days').change(function () {
|
|
forceMinMax($(this));
|
|
time_range = $(this).val();
|
|
setLocalStorage('home_stats_days', time_range);
|
|
getHomeStats(time_range, stats_type);
|
|
});
|
|
|
|
$('#watched-stats-days').tooltip({ container: 'body', placement: 'top', html: true });
|
|
</script>
|
|
% endif
|
|
% if 'library_stats' in config['home_sections']:
|
|
<script>
|
|
function getLibraryStats() {
|
|
$.ajax({
|
|
url: 'library_stats',
|
|
type: 'GET',
|
|
cache: false,
|
|
async: true,
|
|
data: { },
|
|
complete: function (xhr, status) {
|
|
$("#library-stats").html(xhr.responseText);
|
|
statsCardCallback();
|
|
}
|
|
});
|
|
}
|
|
getLibraryStats();
|
|
</script>
|
|
% endif
|
|
% if 'recently_added' in config['home_sections']:
|
|
<script>
|
|
function recentlyAdded(recently_added_count, recently_added_type) {
|
|
showMsg("Loading recently added items...", true, false, 0);
|
|
|
|
$.ajax({
|
|
url: 'get_recently_added',
|
|
type: 'GET',
|
|
async: true,
|
|
data: {
|
|
count: recently_added_count,
|
|
media_type: recently_added_type
|
|
},
|
|
beforeSend: function () {
|
|
$(".dashboard-recent-media-row").animate({ scrollLeft: 0 }, 1000);
|
|
},
|
|
complete: function (xhr, status) {
|
|
$("#recentlyAdded").html(xhr.responseText);
|
|
$('#ajaxMsg').fadeOut();
|
|
highlightScrollerButton("#recently-added");
|
|
paginateScroller("#recently-added", ".paginate-added");
|
|
}
|
|
});
|
|
}
|
|
|
|
var recently_added_count = getLocalStorage('home_stats_recently_added_count', 50);
|
|
var recently_added_type = getLocalStorage('home_stats_recently_added_type', 'all');;
|
|
|
|
$('#recently-added-toggle-' + recently_added_type).prop('checked', true);
|
|
$('#recently-added-toggle-' + recently_added_type).closest('label').addClass('active');
|
|
$('#recently-added-count').val(recently_added_count);
|
|
|
|
function recentlyAddedConnected() {
|
|
recentlyAdded(recently_added_count, recently_added_type);
|
|
}
|
|
|
|
$('#recently-added-toggles').on('change', function () {
|
|
$('#recently-added-toggles > label').removeClass('active');
|
|
selected_filter = $('input[name=recently-added-toggle]:checked', '#recently-added-toggles');
|
|
$(selected_filter).closest('label').addClass('active');
|
|
recently_added_type = $(selected_filter).val();
|
|
setLocalStorage('home_stats_recently_added_type', recently_added_type);
|
|
recentlyAdded(recently_added_count, recently_added_type);
|
|
});
|
|
|
|
$('#recently-added-count').change(function () {
|
|
forceMinMax($(this));
|
|
recently_added_count = $(this).val();
|
|
setLocalStorage('home_stats_recently_added_count', recently_added_count);
|
|
recentlyAdded(recently_added_count, recently_added_type);
|
|
});
|
|
|
|
$('#recently-added-count').tooltip({ container: 'body', placement: 'top', html: true });
|
|
|
|
$('#recently-added-xml').on('tripleclick', function () {
|
|
openPlexXML('/library/recentlyAdded', false, {'X-Plex-Container-Start': 0, 'X-Plex-Container-Size': recently_added_count});
|
|
});
|
|
</script>
|
|
% endif
|
|
% if _session['user_group'] == 'admin' and config['update_show_changelog']:
|
|
<script>
|
|
$.ajax({
|
|
url: 'get_changelog',
|
|
data: {
|
|
since_prev_release: true,
|
|
update_shown: true
|
|
},
|
|
cache: false,
|
|
async: true,
|
|
complete: function (xhr, status) {
|
|
$("#changelog-modal .modal-body").html(xhr.responseText);
|
|
$('#changelog-modal').modal({
|
|
backdrop: 'static',
|
|
keyboard: false
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
% endif
|
|
</%def>
|