diff --git a/data/interfaces/default/js/tables/user_ips.js b/data/interfaces/default/js/tables/user_ips.js
index 7321e1b3..9c8cc411 100644
--- a/data/interfaces/default/js/tables/user_ips.js
+++ b/data/interfaces/default/js/tables/user_ips.js
@@ -24,13 +24,11 @@ user_ip_table_options = {
},
"searchable": false,
"width": "15%",
- "className": "no-wrap"
+ "className": "no-wrap hidden-xs"
},
{
"targets": [1],
- "data":"ip_address",
- "width": "15%",
- "className": "modal-control no-wrap",
+ "data": "ip_address",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData) {
if (isPrivateIP(cellData)) {
@@ -46,31 +44,59 @@ user_ip_table_options = {
$(td).html('n/a');
}
},
- "width": "15%"
+ "width": "15%",
+ "className": "no-wrap modal-control-ip"
},
{
"targets": [2],
- "data":"play_count",
- "width": "10%",
- "className": "hidden-xs"
+ "data":"platform",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData) {
+ $(td).html(' ' + cellData + '');
+ } else {
+ $(td).html('n/a');
+ }
+ },
+ "width": "15%",
+ "className": "no-wrap hidden-md hidden-sm hidden-xs modal-control"
},
{
"targets": [3],
- "data":"platform",
- "width": "15%",
- "className": "hidden-xs"
+ "data":"last_watched",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData !== '') {
+ if (rowData['media_type'] === 'movie' || rowData['media_type'] === 'episode') {
+ var transcode_dec = '';
+ if (rowData['video_decision'] === 'transcode') {
+ transcode_dec = ' ';
+ }
+ $(td).html('
');
+ } else if (rowData['media_type'] === 'track') {
+ $(td).html('');
+ } else if (rowData['media_type']) {
+ $(td).html('' + cellData + '');
+ } else {
+ $(td).html('n/a');
+ }
+ }
+ },
+ "className": "hidden-sm hidden-xs"
},
{
"targets": [4],
- "data":"last_watched",
- "width": "30%",
- "className": "hidden-sm hidden-xs"
- }
+ "data":"play_count",
+ "searchable": false,
+ "width": "10%"
+ }
],
"drawCallback": function (settings) {
// Jump to top of page
// $('html,body').scrollTop(0);
$('#ajaxMsg').fadeOut();
+ // Create the tooltips.
+ $('.info-modal').each(function () {
+ $(this).tooltip();
+ });
},
"preDrawCallback": function(settings) {
var msg = " Fetching rows...
";
@@ -83,6 +109,25 @@ $('#user_ip_table').on('mouseenter', 'td.modal-control span', function () {
});
$('#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 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();
+});
+
+$('#user_ip_table').on('click', 'td.modal-control-ip', function () {
var tr = $(this).parents('tr');
var row = user_ip_table.row( tr );
var rowData = row.data();
diff --git a/data/interfaces/default/js/tables/users.js b/data/interfaces/default/js/tables/users.js
index 5dba864b..c3e022e3 100644
--- a/data/interfaces/default/js/tables/users.js
+++ b/data/interfaces/default/js/tables/users.js
@@ -34,7 +34,7 @@ users_list_table_options = {
{
"targets": [1],
"data": "friendly_name",
- "createdCell": function (td, cellData, rowData, row, col) {
+ "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
if (rowData['user_id'] > 0) {
$(td).html('' + cellData + '');
@@ -45,6 +45,7 @@ users_list_table_options = {
$(td).html(cellData);
}
},
+ "width": "15%"
},
{
"targets": [2],
@@ -57,34 +58,126 @@ users_list_table_options = {
}
},
"searchable": false,
- "className": "hidden-xs",
+ "width": "15%",
+ "className": "no-wrap hidden-xs"
},
{
"targets": [3],
"data": "ip_address",
- "render": function ( data, type, full ) {
- if (data) {
- return data;
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData) {
+ if (isPrivateIP(cellData)) {
+ if (cellData != '') {
+ $(td).html(cellData);
+ } else {
+ $(td).html('n/a');
+ }
+ } else {
+ $(td).html(' ' + cellData + '');
+ }
} else {
- return "n/a";
+ $(td).html('n/a');
}
},
- "className": "hidden-xs",
+ "width": "15%",
+ "className": "no-wrap hidden-md hidden-sm hidden-xs modal-control-ip"
},
{
"targets": [4],
+ "data":"platform",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData) {
+ $(td).html(' ' + cellData + '');
+ } else {
+ $(td).html('n/a');
+ }
+ },
+ "width": "15%",
+ "className": "no-wrap hidden-md hidden-sm hidden-xs modal-control"
+ },
+ {
+ "targets": [5],
+ "data":"last_watched",
+ "createdCell": function (td, cellData, rowData, row, col) {
+ if (cellData !== '') {
+ if (rowData['media_type'] === 'movie' || rowData['media_type'] === 'episode') {
+ var transcode_dec = '';
+ if (rowData['video_decision'] === 'transcode') {
+ transcode_dec = ' ';
+ }
+ $(td).html('');
+ } else if (rowData['media_type'] === 'track') {
+ $(td).html('');
+ } else if (rowData['media_type']) {
+ $(td).html('' + cellData + '');
+ } else {
+ $(td).html('n/a');
+ }
+ }
+ },
+ "className": "hidden-sm hidden-xs"
+ },
+ {
+ "targets": [6],
"data": "plays",
- "searchable": false
- }
+ "searchable": false,
+ "width": "10%"
+ }
],
"drawCallback": function (settings) {
// Jump to top of page
//$('html,body').scrollTop(0);
$('#ajaxMsg').fadeOut();
+ // Create the tooltips.
+ $('.info-modal').each(function () {
+ $(this).tooltip();
+ });
},
"preDrawCallback": function(settings) {
var msg = " Fetching rows...
";
showMsg(msg, false, false, 0)
}
}
+
+$('#users_list_table').on('click', 'td.modal-control', function () {
+ var tr = $(this).parents('tr');
+ var row = users_list_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();
+});
+
+$('#users_list_table').on('click', 'td.modal-control-ip', function () {
+ var tr = $(this).parents('tr');
+ var row = users_list_table.row(tr);
+ var rowData = row.data();
+
+ function getUserLocation(ip_address) {
+ if (isPrivateIP(ip_address)) {
+ return "n/a"
+ } else {
+ $.ajax({
+ url: 'get_ip_address_details',
+ data: { ip_address: ip_address },
+ async: true,
+ complete: function (xhr, status) {
+ $("#ip-info-modal").html(xhr.responseText);
+ }
+ });
+ }
+ }
+
+ getUserLocation(rowData['ip_address']);
+});
\ No newline at end of file
diff --git a/data/interfaces/default/user.html b/data/interfaces/default/user.html
index 366d46dc..4727be64 100644
--- a/data/interfaces/default/user.html
+++ b/data/interfaces/default/user.html
@@ -131,11 +131,11 @@ from plexpy import helpers
- Last seen |
+ Last Seen |
IP Address |
- Play Count |
- Platform (Last Seen) |
+ Last Platform |
Last Watched |
+ Play Count |
@@ -181,7 +181,6 @@ from plexpy import helpers
-
@@ -224,7 +223,9 @@ from plexpy import helpers
-
diff --git a/data/interfaces/default/users.html b/data/interfaces/default/users.html
index ddb52843..37cf9bc7 100644
--- a/data/interfaces/default/users.html
+++ b/data/interfaces/default/users.html
@@ -23,12 +23,18 @@
User |
Last Seen |
Last Known IP |
+ Last Platform |
+ Last Watched |
Total Plays |
+
+
+
+
diff --git a/plexpy/users.py b/plexpy/users.py
index fcc9cf94..fb31916c 100644
--- a/plexpy/users.py
+++ b/plexpy/users.py
@@ -24,13 +24,19 @@ class Users(object):
def get_user_list(self, kwargs=None):
data_tables = datatables.DataTables()
- columns = ['users.user_id as user_id',
+ columns = ['session_history.id',
+ 'users.user_id as user_id',
'users.custom_avatar_url as thumb',
'(case when users.friendly_name is null then users.username else \
users.friendly_name end) as friendly_name',
'MAX(session_history.started) as last_seen',
'session_history.ip_address as ip_address',
'COUNT(session_history.id) as plays',
+ 'session_history.player as platform',
+ 'session_history_metadata.full_title as last_watched',
+ 'session_history_metadata.media_type',
+ 'session_history.rating_key as rating_key',
+ 'session_history_media_info.video_decision',
'users.username as user'
]
try:
@@ -38,9 +44,15 @@ class Users(object):
columns=columns,
custom_where=[],
group_by=['users.user_id'],
- join_types=['LEFT OUTER JOIN'],
- join_tables=['session_history'],
- join_evals=[['session_history.user_id', 'users.user_id']],
+ join_types=['LEFT OUTER JOIN',
+ 'LEFT OUTER JOIN',
+ 'LEFT OUTER JOIN'],
+ join_tables=['session_history',
+ 'session_history_metadata',
+ 'session_history_media_info'],
+ join_evals=[['session_history.user_id', 'users.user_id'],
+ ['session_history.id', 'session_history_metadata.id'],
+ ['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query.")
@@ -59,10 +71,16 @@ class Users(object):
else:
user_thumb = item['thumb']
- row = {"plays": item['plays'],
+ row = {"id": item['id'],
+ "plays": item['plays'],
"last_seen": item['last_seen'],
- "friendly_name": item["friendly_name"],
- "ip_address": item["ip_address"],
+ "friendly_name": item['friendly_name'],
+ "ip_address": item['ip_address'],
+ "platform": item['platform'],
+ "last_watched": item['last_watched'],
+ "media_type": item['media_type'],
+ "rating_key": item['rating_key'],
+ "video_decision": item['video_decision'],
"thumb": user_thumb,
"user": item["user"],
"user_id": item['user_id']
@@ -81,13 +99,22 @@ class Users(object):
def get_user_unique_ips(self, kwargs=None, custom_where=None):
data_tables = datatables.DataTables()
- columns = ['session_history.started as last_seen',
+ # Change custom_where column name due to ambiguous column name after JOIN
+ custom_where[0][0] = 'custom_user_id' if custom_where[0][0] == 'user_id' else custom_where[0][0]
+
+ columns = ['session_history.id',
+ 'session_history.started as last_seen',
'session_history.ip_address as ip_address',
'COUNT(session_history.id) as play_count',
'session_history.player as platform',
'session_history_metadata.full_title as last_watched',
+ 'session_history_metadata.media_type',
+ 'session_history.rating_key as rating_key',
+ 'session_history_media_info.video_decision',
'session_history.user as user',
- 'session_history.user_id as user_id'
+ 'session_history.user_id as custom_user_id',
+ '(case when users.friendly_name is null then users.username else \
+ users.friendly_name end) as friendly_name'
]
try:
@@ -95,9 +122,15 @@ class Users(object):
columns=columns,
custom_where=custom_where,
group_by=['ip_address'],
- join_types=['JOIN'],
- join_tables=['session_history_metadata'],
- join_evals=[['session_history.id', 'session_history_metadata.id']],
+ join_types=['JOIN',
+ 'JOIN',
+ 'JOIN'],
+ join_tables=['users',
+ 'session_history_metadata',
+ 'session_history_media_info'],
+ join_evals=[['session_history.user_id', 'users.user_id'],
+ ['session_history.id', 'session_history_metadata.id'],
+ ['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query.")
@@ -111,11 +144,16 @@ class Users(object):
rows = []
for item in results:
- row = {"last_seen": item['last_seen'],
+ row = {"id": item['id'],
+ "last_seen": item['last_seen'],
"ip_address": item['ip_address'],
"play_count": item['play_count'],
"platform": item['platform'],
- "last_watched": item['last_watched']
+ "last_watched": item['last_watched'],
+ "media_type": item['media_type'],
+ "rating_key": item['rating_key'],
+ "video_decision": item['video_decision'],
+ "friendly_name": item['friendly_name']
}
rows.append(row)