diff --git a/data/interfaces/default/css/plexpy.css b/data/interfaces/default/css/plexpy.css index 1a0d5658..7d715a3c 100644 --- a/data/interfaces/default/css/plexpy.css +++ b/data/interfaces/default/css/plexpy.css @@ -1646,6 +1646,30 @@ input[type="color"], width: 250px; z-index: 9999; } +.tooltip.top .tooltip-arrow { + border-top-color: #fff; +} +.tooltip.right .tooltip-arrow { + border-right-color: #fff; +} +.tooltip.bottom .tooltip-arrow { + border-bottom-color: #fff; +} +.tooltip.left .tooltip-arrow { + border-left-color: #fff; +} +.tooltip-inner { + color: #000; + background: #fff; + border: 0; + font-weight: bold; +} +.history-title .popover.right { + margin-left: 12px; +} +.history-title .popover.right .popover-content { + padding: 5px 8px; +} #updatebar { background-color: #444; color: #999999; diff --git a/data/interfaces/default/history.html b/data/interfaces/default/history.html index 9546b94b..9e1ec5f6 100644 --- a/data/interfaces/default/history.html +++ b/data/interfaces/default/history.html @@ -79,7 +79,6 @@ }); } }); - }); diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index a1c313b2..b2ba2b98 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -174,7 +174,9 @@ DOCUMENTATION :: END
Watch History for ${data['title']}
-
@@ -184,8 +186,8 @@ DOCUMENTATION :: END Delete Time User - Platform IP Address + Platform Title Started Paused @@ -236,7 +238,6 @@ DOCUMENTATION :: END <%def name="javascriptIncludes()"> - @@ -269,6 +270,18 @@ DOCUMENTATION :: END $(colvis.button()).appendTo('div.colvis-button-bar'); clearSearchButton('history_table', history_table); + + $('#row-edit-mode').click(function() { + if ($(this).hasClass('active')) { + $('.delete-control').each(function() { + $(this).addClass('hidden'); + }); + } else { + $('.delete-control').each(function() { + $(this).removeClass('hidden'); + }); + } + }); }); % elif data['type'] == 'show': @@ -289,6 +302,18 @@ DOCUMENTATION :: END $(colvis.button()).appendTo('div.colvis-button-bar'); clearSearchButton('history_table', history_table); + + $('#row-edit-mode').click(function() { + if ($(this).hasClass('active')) { + $('.delete-control').each(function() { + $(this).addClass('hidden'); + }); + } else { + $('.delete-control').each(function() { + $(this).removeClass('hidden'); + }); + } + }); }); % endif diff --git a/data/interfaces/default/js/tables/history_table.js b/data/interfaces/default/js/tables/history_table.js index 65edc7c8..9898cc1b 100644 --- a/data/interfaces/default/js/tables/history_table.js +++ b/data/interfaces/default/js/tables/history_table.js @@ -34,6 +34,7 @@ history_table_options = { "createdCell": function (td, cellData, rowData, row, col) { $(td).html(''); }, + "width": "5%", "className": "delete-control no-wrap hidden", "searchable": false, "orderable": false @@ -49,6 +50,7 @@ history_table_options = { } }, "searchable": false, + "width": "8%", "className": "no-wrap" }, { @@ -65,6 +67,7 @@ history_table_options = { $(td).html(cellData); } }, + "width": "8%", "className": "no-wrap hidden-xs" }, { @@ -85,6 +88,7 @@ history_table_options = { $(td).html('n/a'); } }, + "width": "8%", "className": "no-wrap hidden-md hidden-sm hidden-xs modal-control-ip" }, { @@ -92,9 +96,18 @@ history_table_options = { "data":"player", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== '') { - $(td).html(' ' + cellData + ''); + var transcode_dec = ''; + if (rowData['video_decision'] === 'transcode') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'copy') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'direct play' || rowData['video_decision'] === '') { + transcode_dec = ' '; + } + $(td).html('
' + transcode_dec + ' ' + cellData + '
'); } }, + "width": "15%", "className": "no-wrap hidden-md hidden-sm hidden-xs modal-control" }, { @@ -102,19 +115,27 @@ history_table_options = { "data":"full_title", "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('
' + cellData + '
' + transcode_dec + '
'); + var media_type = ''; + var thumb_popover = ''; + if (rowData['media_type'] === 'movie') { + media_type = ''; + thumb_popover = '' + cellData + ' (' + rowData['year'] + ')' + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); + } else if (rowData['media_type'] === 'episode') { + media_type = ''; + thumb_popover = '' + cellData + ' \ + (S' + ('00' + rowData['parent_media_index']).slice(-2) + 'E' + ('00' + rowData['media_index']).slice(-2) + ')' + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else if (rowData['media_type'] === 'track') { - $(td).html('
' + cellData + '
'); + media_type = ''; + thumb_popover = '' + cellData + ' (' + rowData['parent_title'] + ')' + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else { $(td).html('' + cellData + ''); } } - } + }, + "width": "35%" }, { "targets": [6], @@ -127,6 +148,7 @@ history_table_options = { } }, "searchable": false, + "width": "5%", "className": "no-wrap hidden-sm hidden-xs" }, { @@ -140,6 +162,7 @@ history_table_options = { } }, "searchable": false, + "width": "5%", "className": "no-wrap hidden-md hidden-sm hidden-xs" }, { @@ -153,6 +176,7 @@ history_table_options = { } }, "searchable": false, + "width": "5%", "className": "no-wrap hidden-sm hidden-xs" }, { @@ -166,6 +190,7 @@ history_table_options = { } }, "searchable": false, + "width": "5%", "className": "no-wrap hidden-xs" }, { @@ -173,27 +198,37 @@ history_table_options = { "data":"percent_complete", "render": function ( data, type, full ) { if (data > 80) { - return '' + return '' } else if (data > 40) { - return '' + return '' } else { - return '' + return '' } }, "searchable": false, "orderable": false, "className": "no-wrap hidden-md hidden-sm hidden-xs", - "width": "10px" + "width": "1%" }, ], "drawCallback": function (settings) { // Jump to top of page // $('html,body').scrollTop(0); $('#ajaxMsg').fadeOut(); + // Create the tooltips. - $('.info-modal').each(function() { - $(this).tooltip(); + $('.transcode-tooltip').tooltip(); + $('.media-type-tooltip').tooltip(); + $('.watched-tooltip').tooltip(); + $('.thumb-tooltip').popover({ + html: true, + trigger: 'hover', + placement: 'right', + content: function () { + return '
'; + } }); + if ($('#row-edit-mode').hasClass('active')) { $('.delete-control').each(function() { $(this).removeClass('hidden'); diff --git a/data/interfaces/default/js/tables/user_ips.js b/data/interfaces/default/js/tables/user_ips.js index 9c8cc411..5968b67a 100644 --- a/data/interfaces/default/js/tables/user_ips.js +++ b/data/interfaces/default/js/tables/user_ips.js @@ -52,7 +52,15 @@ user_ip_table_options = { "data":"platform", "createdCell": function (td, cellData, rowData, row, col) { if (cellData) { - $(td).html(' ' + cellData + ''); + var transcode_dec = ''; + if (rowData['video_decision'] === 'transcode') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'copy') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'direct play' || rowData['video_decision'] === '') { + transcode_dec = ' '; + } + $(td).html('
' + transcode_dec + ' ' + cellData + '
'); } else { $(td).html('n/a'); } @@ -65,14 +73,20 @@ user_ip_table_options = { "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('
' + cellData + '
' + transcode_dec + '
'); + var media_type = ''; + var thumb_popover = '' + if (rowData['media_type'] === 'movie') { + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html(''); + } else if (rowData['media_type'] === 'episode') { + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html(''); } else if (rowData['media_type'] === 'track') { - $(td).html('
' + cellData + '
'); + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else if (rowData['media_type']) { $(td).html('' + cellData + ''); } else { @@ -93,10 +107,20 @@ user_ip_table_options = { // Jump to top of page // $('html,body').scrollTop(0); $('#ajaxMsg').fadeOut(); + // Create the tooltips. - $('.info-modal').each(function () { - $(this).tooltip(); + $('.transcode-tooltip').tooltip(); + $('.media-type-tooltip').tooltip(); + $('.watched-tooltip').tooltip(); + $('.thumb-tooltip').popover({ + html: true, + trigger: 'hover', + placement: 'right', + content: function () { + return '
'; + } }); + }, "preDrawCallback": function(settings) { var msg = "
 Fetching rows...
"; diff --git a/data/interfaces/default/js/tables/users.js b/data/interfaces/default/js/tables/users.js index c3e022e3..c3d1ae1e 100644 --- a/data/interfaces/default/js/tables/users.js +++ b/data/interfaces/default/js/tables/users.js @@ -18,7 +18,7 @@ users_list_table_options = { "columnDefs": [ { "targets": [0], - "data": "thumb", + "data": "user_thumb", "createdCell": function (td, cellData, rowData, row, col) { if (cellData === '') { $(td).html('User Logo'); @@ -28,8 +28,8 @@ users_list_table_options = { }, "orderable": false, "searchable": false, - "className": "users-poster-face", - "width": "40px" + "width": "5%", + "className": "users-poster-face" }, { "targets": [1], @@ -87,7 +87,15 @@ users_list_table_options = { "data":"platform", "createdCell": function (td, cellData, rowData, row, col) { if (cellData) { - $(td).html(' ' + cellData + ''); + var transcode_dec = ''; + if (rowData['video_decision'] === 'transcode') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'copy') { + transcode_dec = ' '; + } else if (rowData['video_decision'] === 'direct play' || rowData['video_decision'] === '') { + transcode_dec = ' '; + } + $(td).html('
' + transcode_dec + ' ' + cellData + '
'); } else { $(td).html('n/a'); } @@ -100,14 +108,20 @@ users_list_table_options = { "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('
' + cellData + '
' + transcode_dec + '
'); + var media_type = ''; + var thumb_popover = '' + if (rowData['media_type'] === 'movie') { + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html(''); + } else if (rowData['media_type'] === 'episode') { + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html(''); } else if (rowData['media_type'] === 'track') { - $(td).html('
' + cellData + '
'); + media_type = ''; + thumb_popover = '' + cellData + '' + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else if (rowData['media_type']) { $(td).html('' + cellData + ''); } else { @@ -129,10 +143,20 @@ users_list_table_options = { // Jump to top of page //$('html,body').scrollTop(0); $('#ajaxMsg').fadeOut(); + // Create the tooltips. - $('.info-modal').each(function () { - $(this).tooltip(); + $('.transcode-tooltip').tooltip(); + $('.media-type-tooltip').tooltip(); + $('.watched-tooltip').tooltip(); + $('.thumb-tooltip').popover({ + html: true, + trigger: 'hover', + placement: 'right', + content: function () { + return '
'; + } }); + }, "preDrawCallback": function(settings) { var msg = "
 Fetching rows...
"; diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index cecee027..b60c654b 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -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 # it under the terms of the GNU General Public License as published by @@ -36,6 +36,13 @@ class DataFactory(object): 'session_history.player', 'session_history.ip_address', 'session_history_metadata.full_title as full_title', + 'session_history_metadata.thumb', + 'session_history_metadata.parent_thumb', + 'session_history_metadata.grandparent_thumb', + 'session_history_metadata.media_index', + 'session_history_metadata.parent_media_index', + 'session_history_metadata.parent_title', + 'session_history_metadata.year', 'session_history.started', 'session_history.paused_counter', 'session_history.stopped', @@ -81,12 +88,24 @@ class DataFactory(object): rows = [] for item in history: + if item["media_type"] == 'episode' and item["parent_thumb"]: + thumb = item["parent_thumb"] + elif item["media_type"] == 'episode': + thumb = item["grandparent_thumb"] + else: + thumb = item["thumb"] + row = {"id": item['id'], "date": item['date'], "friendly_name": item['friendly_name'], "player": item["player"], "ip_address": item["ip_address"], "full_title": item["full_title"], + "thumb": thumb, + "media_index": item["media_index"], + "parent_media_index": item["parent_media_index"], + "parent_title": item["parent_title"], + "year": item["year"], "started": item["started"], "paused_counter": item["paused_counter"], "stopped": item["stopped"], @@ -411,7 +430,6 @@ class DataFactory(object): else: return None - print result stream_output = {} for item in result: @@ -512,13 +530,15 @@ class DataFactory(object): metadata = {} for item in result: - directors = item['directors'].split(';') - writers = item['writers'].split(';') - actors = item['actors'].split(';') - genres = item['genres'].split(';') + directors = item['directors'].split(';') if item['directors'] else [] + writers = item['writers'].split(';') if item['writers'] else [] + actors = item['actors'].split(';') if item['actors'] else [] + genres = item['genres'].split(';') if item['genres'] else [] metadata = {'type': item['media_type'], 'rating_key': item['rating_key'], + 'parent_rating_key': item['parent_rating_key'], + 'grandparent_rating_key': item['grandparent_rating_key'], 'grandparent_title': item['grandparent_title'], 'parent_index': item['parent_media_index'], 'parent_title': item['parent_title'], diff --git a/plexpy/users.py b/plexpy/users.py index fb31916c..8a24b38b 100644 --- a/plexpy/users.py +++ b/plexpy/users.py @@ -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 # it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ class Users(object): columns = ['session_history.id', 'users.user_id as user_id', - 'users.custom_avatar_url as thumb', + 'users.custom_avatar_url as user_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', @@ -34,6 +34,9 @@ class Users(object): 'COUNT(session_history.id) as plays', 'session_history.player as platform', 'session_history_metadata.full_title as last_watched', + 'session_history_metadata.thumb', + 'session_history_metadata.parent_thumb', + 'session_history_metadata.grandparent_thumb', 'session_history_metadata.media_type', 'session_history.rating_key as rating_key', 'session_history_media_info.video_decision', @@ -66,10 +69,17 @@ class Users(object): rows = [] for item in users: - if not item['thumb'] or item['thumb'] == '': + if item["media_type"] == 'episode' and item["parent_thumb"]: + thumb = item["parent_thumb"] + elif item["media_type"] == 'episode': + thumb = item["grandparent_thumb"] + else: + thumb = item["thumb"] + + if not item['user_thumb'] or item['user_thumb'] == '': user_thumb = common.DEFAULT_USER_THUMB else: - user_thumb = item['thumb'] + user_thumb = item['user_thumb'] row = {"id": item['id'], "plays": item['plays'], @@ -78,10 +88,11 @@ class Users(object): "ip_address": item['ip_address'], "platform": item['platform'], "last_watched": item['last_watched'], + "thumb": thumb, "media_type": item['media_type'], "rating_key": item['rating_key'], "video_decision": item['video_decision'], - "thumb": user_thumb, + "user_thumb": user_thumb, "user": item["user"], "user_id": item['user_id'] } @@ -108,6 +119,9 @@ class Users(object): 'COUNT(session_history.id) as play_count', 'session_history.player as platform', 'session_history_metadata.full_title as last_watched', + 'session_history_metadata.thumb', + 'session_history_metadata.parent_thumb', + 'session_history_metadata.grandparent_thumb', 'session_history_metadata.media_type', 'session_history.rating_key as rating_key', 'session_history_media_info.video_decision', @@ -144,12 +158,20 @@ class Users(object): rows = [] for item in results: + if item["media_type"] == 'episode' and item["parent_thumb"]: + thumb = item["parent_thumb"] + elif item["media_type"] == 'episode': + thumb = item["grandparent_thumb"] + else: + thumb = item["thumb"] + 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'], + "thumb": thumb, "media_type": item['media_type'], "rating_key": item['rating_key'], "video_decision": item['video_decision'],