mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 06:00:51 -07:00
Template the Datatables JS
Add Links to user screen Add Public IP list to user screen Add Watch history to user screen
This commit is contained in:
parent
c4504d8be0
commit
6a026d510d
12 changed files with 536 additions and 335 deletions
|
@ -25,7 +25,7 @@
|
|||
<!-- <img src="interfaces/default/images/platforms/roku.png"> platform image -->
|
||||
</div>
|
||||
<div class="dashboard-activity-metadata-user">
|
||||
${a['user']} is ${a['state']}
|
||||
<a href="user?user=${a['user']}">${a['user']}</a> is ${a['state']}
|
||||
</div>
|
||||
<div class="dashboard-activity-metadata-title">
|
||||
% if a['type'] == 'episode':
|
||||
|
|
|
@ -208,3 +208,13 @@ function getPlatformImagePath(platformName) {
|
|||
return 'interfaces/default/images/platforms/default.png';
|
||||
}
|
||||
}
|
||||
|
||||
function isPrivateIP(ip_address) {
|
||||
var parts = ip_address.split('.');
|
||||
if (parts[0] === '10' ||
|
||||
(parts[0] === '172' && (parseInt(parts[1], 10) >= 16 && parseInt(parts[1], 10) <= 31)) ||
|
||||
(parts[0] === '192' && parts[1] === '168')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -20,7 +20,7 @@ history_table_options = {
|
|||
"infoFiltered":"(filtered from _MAX_ total entries)",
|
||||
"emptyTable": "No data in table",
|
||||
},
|
||||
"stateSave": true,
|
||||
"stateSave": false,
|
||||
"sPaginationType": "bootstrap",
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
|
@ -48,7 +48,14 @@ history_table_options = {
|
|||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"data":"user"
|
||||
"data":"user",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
if (cellData !== '') {
|
||||
$(td).html('<a href="user?user=' + cellData + '">' + cellData + '</a>');
|
||||
} else {
|
||||
$(td).html(cellData);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
|
|
41
data/interfaces/default/js/tables/logs.js
Normal file
41
data/interfaces/default/js/tables/logs.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
$('#log_table').dataTable( {
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
"ajax": {
|
||||
"url": "getLog"
|
||||
},
|
||||
"sPaginationType": "bootstrap",
|
||||
"order": [ 0, 'desc'],
|
||||
"pageLength": 10,
|
||||
"stateSave": true,
|
||||
"language": {
|
||||
"search":"Search: ",
|
||||
"lengthMenu":"Show _MENU_ lines per page",
|
||||
"emptyTable": "No log information available",
|
||||
"info":"Showing _START_ to _END_ of _TOTAL_ lines",
|
||||
"infoEmpty":"Showing 0 to 0 of 0 lines",
|
||||
"infoFiltered":"(filtered from _MAX_ total lines)"},
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"width": "15%"
|
||||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"width": "10%"
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"width": "75%"
|
||||
}
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
$('html,body').scrollTop(0);
|
||||
$('#ajaxMsg').addClass('success').fadeOut();
|
||||
},
|
||||
"preDrawCallback": function(settings) {
|
||||
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
|
||||
$('#ajaxMsg').addClass('success').fadeIn();
|
||||
}
|
||||
});
|
105
data/interfaces/default/js/tables/user_ips.js
Normal file
105
data/interfaces/default/js/tables/user_ips.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
user_ip_table_options = {
|
||||
"destroy": true,
|
||||
"language": {
|
||||
"search": "Search: ",
|
||||
"lengthMenu":"Show _MENU_ entries per page",
|
||||
"info":"Showing _START_ to _END_ of _TOTAL_ results",
|
||||
"infoEmpty":"Showing 0 to 0 of 0 entries",
|
||||
"infoFiltered":"(filtered from _MAX_ total entries)",
|
||||
"emptyTable": "No data in table",
|
||||
},
|
||||
"stateSave": false,
|
||||
"sPaginationType": "bootstrap",
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
"pageLength": 10,
|
||||
"order": [ 0, 'desc'],
|
||||
"autoWidth": false,
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"data":"last_seen",
|
||||
"render": function ( data, type, full ) {
|
||||
return moment(data, "X").fromNow();
|
||||
},
|
||||
"searchable": false,
|
||||
"width": "15%"
|
||||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"data":"ip_address",
|
||||
"width": "15%",
|
||||
"className": "modal-control",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
if (isPrivateIP(cellData)) {
|
||||
$(td).html(cellData);
|
||||
} else {
|
||||
$(td).html('<a href="#ip-info-modal" data-toggle="modal"><span data-toggle="ip-tooltip" data-placement="left" title="IP Address Info" id="ip-info"><i class="icon-map-marker icon-white"></i></span> ' + cellData +'</a>');
|
||||
}
|
||||
},
|
||||
"width": "15%"
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"data":"play_count",
|
||||
"width": "10%"
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"data":"platform",
|
||||
"width": "15%"
|
||||
},
|
||||
{
|
||||
"targets": [4],
|
||||
"data":"last_watched",
|
||||
"width": "30%"
|
||||
}
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
// $('html,body').scrollTop(0);
|
||||
$('#ajaxMsg').addClass('success').fadeOut();
|
||||
},
|
||||
"preDrawCallback": function(settings) {
|
||||
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
|
||||
$('#ajaxMsg').addClass('success').fadeIn();
|
||||
}
|
||||
}
|
||||
|
||||
$('#user_ip_table').on('mouseenter', 'td.modal-control span', function () {
|
||||
$(this).tooltip();
|
||||
});
|
||||
|
||||
$('#user_ip_table').on('click', 'td.modal-control', function () {
|
||||
var tr = $(this).parents('tr');
|
||||
var row = user_ip_table.row( tr );
|
||||
var rowData = row.data();
|
||||
|
||||
function getUserLocation(ip_address) {
|
||||
if (isPrivateIP(ip_address)) {
|
||||
return "n/a"
|
||||
} else {
|
||||
$.ajax({
|
||||
url: 'http://ip-api.com/json/' + ip_address,
|
||||
cache: true,
|
||||
async: true,
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
$('#ip_address').html(ip_address);
|
||||
$('#country').html(data.country);
|
||||
$('#city').html(data.city);
|
||||
$('#region').html(data.regionName);
|
||||
$('#timezone').html(data.timezone);
|
||||
$('#lat').html(data.lat);
|
||||
$('#lon').html(data.lon);
|
||||
$('#isp').html(data.isp);
|
||||
$('#org').html(data.org);
|
||||
$('#as').html(data.as);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getUserLocation(rowData['ip_address']);
|
||||
});
|
77
data/interfaces/default/js/tables/users.js
Normal file
77
data/interfaces/default/js/tables/users.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
users_list_table_options = {
|
||||
"language": {
|
||||
"search": "Search: ",
|
||||
"lengthMenu":"Show _MENU_ entries per page",
|
||||
"info":"Showing _START_ to _END_ of _TOTAL_ active users",
|
||||
"infoEmpty":"Showing 0 to 0 of 0 entries",
|
||||
"infoFiltered":"",
|
||||
"emptyTable": "No data in table",
|
||||
},
|
||||
"destroy": true,
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
"pageLength": 10,
|
||||
"order": [ 0, 'asc'],
|
||||
"ajax": {
|
||||
"url": "get_user_list"
|
||||
},
|
||||
"bLengthChange": true,
|
||||
"bInfo": true,
|
||||
"bAutoWidth": true,
|
||||
"aaSorting": [[ 0, "asc" ]],
|
||||
"bStateSave": true,
|
||||
"bSortClasses": true,
|
||||
"sPaginationType": "bootstrap",
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"data": null,
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
//if (rowData['user_thumb'] === '') {
|
||||
$(td).html('<img src="interfaces/default/images/gravatar-default-80x80.png" alt="User Logo"/>');
|
||||
//} else {
|
||||
// $(td).html('<img src="' + rowData['user_thumb'] + '" alt="User Logo"/>');
|
||||
//}
|
||||
},
|
||||
"orderable": false,
|
||||
"className": "users-poster-face",
|
||||
"width": "40px"
|
||||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"data": "user",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
if (cellData !== '') {
|
||||
$(td).html('<a href="user?user=' + cellData + '">' + cellData + '</a>');
|
||||
} else {
|
||||
$(td).html(cellData);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"data": "time",
|
||||
"render": function ( data, type, full ) {
|
||||
return moment(data, "X").fromNow();
|
||||
}
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"data": "ip_address",
|
||||
"searchable": false
|
||||
},
|
||||
{
|
||||
"targets": [4],
|
||||
"data": "plays"
|
||||
}
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
$('html,body').scrollTop(0);
|
||||
$('#ajaxMsg').addClass('success').fadeOut();
|
||||
},
|
||||
"preDrawCallback": function(settings) {
|
||||
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
|
||||
$('#ajaxMsg').addClass('success').fadeIn();
|
||||
}
|
||||
}
|
|
@ -24,7 +24,12 @@
|
|||
<div class="span12">
|
||||
<div class="wellheader-bg">
|
||||
<div class="dashboard-wellheader-no-chevron">
|
||||
<h2><i class="fa fa-book"></i> Logs</h2>
|
||||
<div class="span9"><h2><i class="fa fa-book"></i> Logs</h2></div>
|
||||
<div class="span3">
|
||||
<div class="pull-right">
|
||||
<h5><a id="menu_link_edit" href="clearLogs"><i class="fa fa-trash-o"></i> Clear log</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,53 +73,7 @@
|
|||
<%def name="javascriptIncludes()">
|
||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
||||
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
$('#log_table').dataTable( {
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
"ajax": {
|
||||
"url": "getLog"
|
||||
},
|
||||
"sPaginationType": "bootstrap",
|
||||
"order": [ 0, 'desc'],
|
||||
"pageLength": 10,
|
||||
"stateSave": true,
|
||||
"language": {
|
||||
"search":"Search: ",
|
||||
"lengthMenu":"Show _MENU_ lines per page",
|
||||
"emptyTable": "No log information available",
|
||||
"info":"Showing _START_ to _END_ of _TOTAL_ lines",
|
||||
"infoEmpty":"Showing 0 to 0 of 0 lines",
|
||||
"infoFiltered":"(filtered from _MAX_ total lines)"},
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"width": "15%"
|
||||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"width": "10%"
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"width": "75%"
|
||||
}
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
$('html,body').scrollTop(0);
|
||||
$('#ajaxMsg').addClass('success').fadeOut();
|
||||
},
|
||||
"preDrawCallback": function(settings) {
|
||||
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
|
||||
$('#ajaxMsg').addClass('success').fadeIn();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="interfaces/default/js/tables/logs.js"></script>
|
||||
<script>
|
||||
var timer;
|
||||
function setRefresh()
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
|
||||
</%def>
|
||||
|
||||
<%def name="body()">
|
||||
<div class="container-fluid">
|
||||
% if user != None:
|
||||
<%def name="body()">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<div class="user-info-wrapper">
|
||||
|
@ -16,7 +17,7 @@
|
|||
<img src="interfaces/default/images/gravatar-default-80x80.png">
|
||||
</div>
|
||||
<div class="user-info-username">
|
||||
Username
|
||||
${user}
|
||||
</div>
|
||||
<div class="user-info-nav">
|
||||
<ul class="user-info-nav">
|
||||
|
@ -28,8 +29,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="profile">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
|
@ -88,22 +89,49 @@
|
|||
<div class="wellheader">
|
||||
<div class="dashboard-wellheader">
|
||||
<h3>Public IP Addresses for <strong>
|
||||
Username
|
||||
${user}
|
||||
</strong></h3>
|
||||
</div>
|
||||
</div>
|
||||
<table id="tableUserIpAddresses" class="display" width="100%">
|
||||
<table id="user_ip_table" class="display" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left"><i class="fa fa-sort"></i> Last seen</th>
|
||||
<th align="left"><i class="fa fa-sort"></i> IP Address</th>
|
||||
<th align="left"><i class="fa fa-sort"></i> Play Count</th>
|
||||
<th align="left"><i class="fa fa-sort"></i> Platform (Last Seen)</th>
|
||||
<th align="left"><i class="fa fa-sort"></i> Location</th>
|
||||
<th align="left"><i class="fa fa-sort"></i> Location</th>
|
||||
<th align="left"> Last Watched</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="ip-info-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||
<h3 id="myModalLabel">IP Address: <strong><span id="ip_address"></span></strong></h3>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-text">
|
||||
<div class="span6">
|
||||
<h4>Location Details</h4>
|
||||
<ul>
|
||||
<li>Country: <strong><span id="country"></span></strong></li>
|
||||
<li>City: <strong><span id="city"></span></strong></li>
|
||||
<li>Region: <strong><span id="region"></span></strong></li>
|
||||
<li>Timezone: <strong><span id="timezone"></span></strong></li>
|
||||
<li>Latitude: <strong><span id="lat"></span></strong></li>
|
||||
<li>Longitude: <strong><span id="lon"></span></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<h4>Connection Details</h4>
|
||||
<ul>
|
||||
<li>ISP: <strong><span id="isp"></span></strong></li>
|
||||
<li>Organization: <strong><span id="org"></span></strong></li>
|
||||
<li>AS: <strong><span id="as"></span></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -116,8 +144,8 @@
|
|||
<div class="wellbg">
|
||||
<div class="wellheader">
|
||||
<div class="dashboard-wellheader">
|
||||
<h3>Watching History for <strong>
|
||||
Username
|
||||
<h3>Watch History for <strong>
|
||||
${user}
|
||||
</strong></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -143,52 +171,6 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<div id="info-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="info-modal" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||
<h3 id="myModalLabel">Stream Info: <strong><span id="modal-stream-info"></span></strong></h3>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-text">
|
||||
<div class="span4">
|
||||
<h4>Stream Details</h4>
|
||||
<ul>
|
||||
<h5>Video</h5>
|
||||
<li>Stream Type: <strong><span id="transcode_video_dec"></span></strong></li>
|
||||
<li>Video Resolution: <strong><span id="transcode_video_resolution"></span>p</strong></li>
|
||||
<li>Video Codec: <strong><span id="transcode_video_codec"></span></strong></li>
|
||||
<li>Video Width: <strong><span id="transcode_video_width"></span></strong></li>
|
||||
<li>Video Height: <strong><span id="transcode_video_height"></span></strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<h5>Audio</h5>
|
||||
<li>Stream Type: <strong><span id="transcode_audio_dec"></span></strong></li>
|
||||
<li>Audio Codec: <strong><span id="transcode_audio_codec"></span></strong></li>
|
||||
<li>Audio Channels: <strong><span id="transcode_audio_channels"></span></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<h4>Media Source Details</h4>
|
||||
<li>Container: <strong><span id="media_container"></span></strong></li>
|
||||
<li>Resolution: <strong><span id="media_resolution"></span>p</strong></li>
|
||||
<li>Bitrate: <strong><span id="media_bitrate"></span> kbps</strong></li>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<h4>Video Source Details</h4>
|
||||
<ul>
|
||||
<li>Width: <strong><span id="video_width"></span></strong></li>
|
||||
<li>Height: <strong><span id="video_height"></span></strong></li>
|
||||
<li>Aspect Ratio: <strong><span id="video_aspect"></span></strong></li>
|
||||
<li>Video Frame Rate: <strong><span id="video_framerate"></span></strong></li>
|
||||
<li>Video Codec: <strong><span id="video_codec"></span></strong></li>
|
||||
</ul>
|
||||
<ul></ul>
|
||||
<h4>Audio Source Details</h4>
|
||||
<ul>
|
||||
<li>Audio Codec: <strong><span id="audio_codec"></span></strong></li>
|
||||
<li>Audio Channels: <strong><span id="audio_channels"></span></strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -196,29 +178,43 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer></footer>
|
||||
</%def>
|
||||
<footer></footer>
|
||||
</%def>
|
||||
|
||||
<%def name="javascriptIncludes()">
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
||||
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
|
||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
||||
|
||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
||||
<script src="interfaces/default/js/tables/user_ips.js"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
history_table_options.ajax = {
|
||||
"url": "get_history",
|
||||
"data": function(d) {
|
||||
d.user = "drzoidberg33";
|
||||
d.user = "${user}";
|
||||
}
|
||||
}
|
||||
|
||||
history_table = $('#history_table').DataTable(history_table_options);
|
||||
history_table.column(2).visible(false); // Hide the title column
|
||||
|
||||
// Hide the title column
|
||||
// history_table.column(5).visible(false);
|
||||
user_ip_table_options.ajax = {
|
||||
"url": "get_user_ips",
|
||||
"data": function(d) {
|
||||
d.user = "${user}";
|
||||
}
|
||||
}
|
||||
user_ip_table = $('#user_ip_table').DataTable(user_ip_table_options);
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
</%def>
|
||||
% else:
|
||||
<div class="clear"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span10 offset1">
|
||||
<h3>Error retrieving user information. Please see the logs for more details.</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
|
@ -23,7 +23,7 @@
|
|||
<div class='row-fluid'>
|
||||
<div class='span12'>
|
||||
<div class='wellbg'>
|
||||
<table id="usersTable" class="display" width="100%">
|
||||
<table id="users_list_table" class="display" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="right" id="avatar"></th>
|
||||
|
@ -48,79 +48,8 @@
|
|||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
||||
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
|
||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
||||
|
||||
<script src="interfaces/default/js/tables/users.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var oTable = $('#usersTable').dataTable({
|
||||
"language": {
|
||||
"search": "Search: ",
|
||||
"lengthMenu":"Show _MENU_ entries per page",
|
||||
"info":"Showing _START_ to _END_ of _TOTAL_ active users",
|
||||
"infoEmpty":"Showing 0 to 0 of 0 entries",
|
||||
"infoFiltered":"",
|
||||
"emptyTable": "No data in table",
|
||||
},
|
||||
"destroy": true,
|
||||
"processing": false,
|
||||
"serverSide": true,
|
||||
"pageLength": 10,
|
||||
"order": [ 0, 'asc'],
|
||||
"ajax": {
|
||||
"url": "get_user_list"
|
||||
},
|
||||
"bLengthChange": true,
|
||||
"bInfo": true,
|
||||
"bAutoWidth": true,
|
||||
"aaSorting": [[ 0, "asc" ]],
|
||||
"bStateSave": true,
|
||||
"bSortClasses": true,
|
||||
"sPaginationType": "bootstrap",
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0],
|
||||
"data": null,
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
//if (rowData['user_thumb'] === '') {
|
||||
$(td).html('<img src="interfaces/default/images/gravatar-default-80x80.png" alt="User Logo"/>');
|
||||
//} else {
|
||||
// $(td).html('<img src="' + rowData['user_thumb'] + '" alt="User Logo"/>');
|
||||
//}
|
||||
},
|
||||
"orderable": false,
|
||||
"className": "users-poster-face",
|
||||
"width": "40px"
|
||||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"data": "user"
|
||||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"data": "time",
|
||||
"render": function ( data, type, full ) {
|
||||
return moment(data, "X").fromNow();
|
||||
}
|
||||
},
|
||||
{
|
||||
"targets": [3],
|
||||
"data": "ip_address",
|
||||
"searchable": false
|
||||
},
|
||||
{
|
||||
"targets": [4],
|
||||
"data": "plays"
|
||||
}
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
$('html,body').scrollTop(0);
|
||||
$('#ajaxMsg').addClass('success').fadeOut();
|
||||
},
|
||||
"preDrawCallback": function(settings) {
|
||||
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
|
||||
$('#ajaxMsg').addClass('success').fadeIn();
|
||||
}
|
||||
});
|
||||
});
|
||||
var users_list_table = $('#users_list_table').DataTable(users_list_table_options);
|
||||
</script>
|
||||
</%def>
|
||||
|
|
|
@ -75,14 +75,14 @@ class DataTables(object):
|
|||
% (column_data['column_string'], table_name, where,
|
||||
order, custom_where)
|
||||
|
||||
# logger.debug(u"Query string: %s" % query)
|
||||
|
||||
filtered = self.ssp_db.select(query)
|
||||
if search_value == '':
|
||||
totalcount = len(filtered)
|
||||
else:
|
||||
totalcount = self.ssp_db.select('SELECT COUNT(*) from %s' % table_name)[0][0]
|
||||
|
||||
# logger.debug(u"Query string: %s" % query)
|
||||
|
||||
result = filtered[start:(start + length)]
|
||||
output = {'result': result,
|
||||
'filteredCount': len(filtered),
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import logger, helpers, request, datatables, config, db
|
||||
|
||||
from xml.dom import minidom
|
||||
|
||||
import plexpy
|
||||
import json
|
||||
|
||||
|
@ -104,6 +104,70 @@ class PlexWatch(object):
|
|||
|
||||
return dict
|
||||
|
||||
def get_user_unique_ips(self, start='', length='', kwargs=None, custom_where=''):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
start = int(start)
|
||||
length = int(length)
|
||||
filtered = []
|
||||
totalcount = 0
|
||||
search_value = ""
|
||||
search_regex = ""
|
||||
order_column = 0
|
||||
order_dir = "desc"
|
||||
|
||||
if 'order[0][dir]' in kwargs:
|
||||
order_dir = kwargs.get('order[0][dir]', "desc")
|
||||
|
||||
if 'order[0][column]' in kwargs:
|
||||
order_column = kwargs.get('order[0][column]', 1)
|
||||
|
||||
if 'search[value]' in kwargs:
|
||||
search_value = kwargs.get('search[value]', "")
|
||||
|
||||
if 'search[regex]' in kwargs:
|
||||
search_regex = kwargs.get('search[regex]', "")
|
||||
|
||||
columns = ['time as last_seen',
|
||||
'ip_address',
|
||||
'COUNT(ip_address) as play_count',
|
||||
'platform',
|
||||
'user',
|
||||
'orig_title as last_watched'
|
||||
]
|
||||
|
||||
query = data_tables.ssp_query(table_name=self.get_user_table_name(),
|
||||
columns=columns,
|
||||
start=start,
|
||||
length=length,
|
||||
order_column=int(order_column),
|
||||
order_dir=order_dir,
|
||||
search_value=search_value,
|
||||
search_regex=search_regex,
|
||||
custom_where=custom_where,
|
||||
group_by='ip_address',
|
||||
kwargs=kwargs)
|
||||
|
||||
results = query['result']
|
||||
|
||||
rows = []
|
||||
for item in results:
|
||||
row = {"last_seen": item['last_seen'],
|
||||
"ip_address": item['ip_address'],
|
||||
"play_count": item['play_count'],
|
||||
"platform": item['platform'],
|
||||
"last_watched": item['last_watched']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_history(self, start='', length='', kwargs=None, custom_where=''):
|
||||
data_tables = datatables.DataTables()
|
||||
|
||||
|
|
|
@ -92,11 +92,11 @@ class WebInterface(object):
|
|||
return serve_template(templatename="users.html", title="Users")
|
||||
|
||||
@cherrypy.expose
|
||||
def user(self):
|
||||
return serve_template(templatename="user.html", title="User")
|
||||
def user(self, user=None):
|
||||
return serve_template(templatename="user.html", title="User", user=user)
|
||||
|
||||
@cherrypy.expose
|
||||
def get_stream_data(self, row_id=None, user='', **kwargs):
|
||||
def get_stream_data(self, row_id=None, user=None, **kwargs):
|
||||
|
||||
plex_watch = plexwatch.PlexWatch()
|
||||
stream_data = plex_watch.get_stream_details(row_id)
|
||||
|
@ -581,3 +581,16 @@ class WebInterface(object):
|
|||
return result
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
||||
@cherrypy.expose
|
||||
def get_user_ips(self, start=0, length=100, custom_where='', **kwargs):
|
||||
|
||||
if 'user' in kwargs:
|
||||
user = kwargs.get('user', "")
|
||||
custom_where = 'user = "%s"' % user
|
||||
|
||||
plex_watch = plexwatch.PlexWatch()
|
||||
history = plex_watch.get_user_unique_ips(start, length, kwargs, custom_where)
|
||||
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(history)
|
Loading…
Add table
Add a link
Reference in a new issue