diff --git a/API.md b/API.md index 8164bd97..a84647db 100644 --- a/API.md +++ b/API.md @@ -88,7 +88,8 @@ Required parameters: section_id (str): The id of the Plex library section Optional parameters: - None + server_id (str): The Plex server identifier of the library section + row_ids (str): Comma separated row ids to delete, e.g. "2,3,8" Returns: None @@ -103,7 +104,7 @@ Required parameters: user_id (str): The id of the Plex user Optional parameters: - None + row_ids (str): Comma separated row ids to delete, e.g. "2,3,8" Returns: None @@ -114,6 +115,21 @@ Returns: Delete and recreate the cache directory. +### delete_history +Delete history rows from Tautulli. + +``` +Required parameters: + row_ids (str): Comma separated row ids to delete, e.g. "65,110,2,3645" + +Optional parameters: + None + +Returns: + None +``` + + ### delete_hosted_images Delete the images uploaded to image hosting services. @@ -146,7 +162,8 @@ Required parameters: section_id (str): The id of the Plex library section Optional parameters: - None + server_id (str): The Plex server identifier of the library section + row_ids (str): Comma separated row ids to delete, e.g. "2,3,8" Returns: None @@ -294,7 +311,7 @@ Required parameters: user_id (str): The id of the Plex user Optional parameters: - None + row_ids (str): Comma separated row ids to delete, e.g. "2,3,8" Returns: None @@ -726,7 +743,6 @@ Returns: "group_count": 1, "group_ids": "1124", "guid": "com.plexapp.agents.thetvdb://121361/6/1?lang=en", - "id": 1124, "ip_address": "xxx.xxx.xxx.xxx", "live": 0, "media_index": 17, @@ -742,6 +758,7 @@ Returns: "player": "Castle-PC", "rating_key": 4348, "reference_id": 1123, + "row_id": 1124, "session_key": null, "started": 1462688107, "state": null, @@ -853,6 +870,7 @@ Returns: [{"art": "/:/resources/show-fanart.jpg", "child_count": "3745", "count": "62", + "is_active": 1, "parent_count": "240", "section_id": "2", "section_name": "TV Shows", @@ -894,7 +912,8 @@ Returns: "do_notify_created": "Checked", "duration": 1578037, "guid": "com.plexapp.agents.thetvdb://121361/6/1?lang=en", - "id": 1128, + "histroy_row_id": 1128, + "is_active": 1, "keep_history": "Checked", "labels": [], "last_accessed": 1462693216, @@ -910,9 +929,11 @@ Returns: "parent_title": "", "plays": 772, "rating_key": 153037, + "row_id": 1, "section_id": 2, "section_name": "TV Shows", "section_type": "Show", + "server_id": "ds48g4r354a8v9byrrtr697g3g79w", "thumb": "/library/metadata/153036/thumb/1462175062", "year": 2016 }, @@ -940,13 +961,16 @@ Returns: "deleted_section": 0, "do_notify": 1, "do_notify_created": 1, + "is_active": 1, "keep_history": 1, "library_art": "/:/resources/movie-fanart.jpg", "library_thumb": "/:/resources/movie.png", "parent_count": null, + "row_id": 1, "section_id": 1, "section_name": "Movies", - "section_type": "movie" + "section_type": "movie", + "server_id": "ds48g4r354a8v9byrrtr697g3g79w" } ``` @@ -1062,10 +1086,11 @@ Get a library's watch time statistics. ``` Required parameters: - section_id (str): The id of the Plex library section + section_id (str): The id of the Plex library section Optional parameters: grouping (int): 0 or 1 + query_days (str): Comma separated days, e.g. "1,7,30,0" Returns: json: @@ -2222,10 +2247,13 @@ Returns: "do_notify": 1, "email": "Jon.Snow.1337@CastleBlack.com", "friendly_name": "Jon Snow", + "is_active": 1, + "is_admin": 0, "is_allow_sync": 1, "is_home_user": 1, "is_restricted": 0, "keep_history": 1, + "row_id": 1, "shared_libraries": ["10", "1", "4", "5", "15", "20", "2"], "user_id": 133788, "user_thumb": "https://plex.tv/users/k10w42309cynaopq/avatar", @@ -2378,6 +2406,7 @@ Required parameters: Optional parameters: grouping (int): 0 or 1 + query_days (str): Comma separated days, e.g. "1,7,30,0" Returns: json: @@ -2421,11 +2450,13 @@ Returns: "filter_music": "", "filter_photos": "", "filter_tv": "", + "is_active": 1, "is_admin": 0, "is_allow_sync": 1, "is_home_user": 1, "is_restricted": 0, "keep_history": 1, + "row_id": 1, "server_token": "PU9cMuQZxJKFBtGqHk68", "shared_libraries": "1;2;3", "thumb": "https://plex.tv/users/k10w42309cynaopq/avatar", @@ -2465,8 +2496,9 @@ Returns: "duration": 2998290, "friendly_name": "Jon Snow", "guid": "com.plexapp.agents.thetvdb://121361/6/1?lang=en", - "id": 1121, + "history_row_id": 1121, "ip_address": "xxx.xxx.xxx.xxx", + "is_active": 1, "keep_history": "Checked", "last_played": "Game of Thrones - The Red Woman", "last_seen": 1462591869, @@ -2480,6 +2512,7 @@ Returns: "player": "Plex Web (Chrome)", "plays": 487, "rating_key": 153037, + "row_id": 1, "thumb": "/library/metadata/153036/thumb/1462175062", "transcode_decision": "transcode", "user_id": 133788, @@ -2741,7 +2774,7 @@ Returns: ### sql Query the Tautulli database with raw SQL. Automatically makes a backup of the database if the latest backup is older then 24h. `api_sql` must be -manually enabled in the config file. +manually enabled in the config file while Tautulli is shut down. ``` Required parameters: diff --git a/data/interfaces/default/css/tautulli.css b/data/interfaces/default/css/tautulli.css index a3865497..50e387c8 100644 --- a/data/interfaces/default/css/tautulli.css +++ b/data/interfaces/default/css/tautulli.css @@ -711,7 +711,6 @@ fieldset[disabled] .form-control { box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); } .users-poster-face { - overflow: hidden; float: left; background-size: cover; background-position: center; @@ -857,7 +856,6 @@ a .users-poster-face:hover { z-index: 2; } .dashboard-activity-info-platform { - padding: 6px !important; background-position: center; background-size: cover; width: 50px; @@ -3119,6 +3117,21 @@ div.dataTables_info { font-weight: bold; border-radius: 2px; } +.inactive-library-tooltip, +.inactive-user-tooltip { + display: inline-block; + position: relative; + width: 100%; + height: 100%; +} +.inactive-library-tooltip i.fa, +.inactive-user-tooltip i.fa { + color: #E5A00D; + position: absolute; + right: 0; + bottom: 0; + text-shadow: 0 0 2px rgba(0,0,0,.5); +} .history-thumbnail-popover { z-index: 2000; padding: 0; @@ -3808,9 +3821,8 @@ a:hover .overlay-refresh-image:hover { } .svg-icon { - padding: 10px; + background-size: calc(100% - 20px) calc(100% - 20px) !important; background-origin: content-box !important; - background-size: contain !important; background-repeat: no-repeat !important; background-position: center !important; } diff --git a/data/interfaces/default/current_activity_instance.html b/data/interfaces/default/current_activity_instance.html index 32989dae..45ee7703 100644 --- a/data/interfaces/default/current_activity_instance.html +++ b/data/interfaces/default/current_activity_instance.html @@ -143,7 +143,7 @@ DOCUMENTATION :: END
% if _session['user_group'] == 'admin' and plexpy.CONFIG.PMS_PLEXPASS and data['session_id']:
- +
% endif diff --git a/data/interfaces/default/history.html b/data/interfaces/default/history.html index bfe32348..16d62a94 100644 --- a/data/interfaces/default/history.html +++ b/data/interfaces/default/history.html @@ -185,17 +185,15 @@ $('#deleteCount').text(history_to_delete.length); $('#confirm-modal-delete').modal(); $('#confirm-modal-delete').one('click', '#confirm-delete', function () { - history_to_delete.forEach(function(row, idx) { - $.ajax({ - url: 'delete_history_rows', - type: 'POST', - data: { row_id: row }, - async: true, - success: function (data) { - var msg = "History deleted"; - showMsg(msg, false, true, 2000); - } - }); + $.ajax({ + url: 'delete_history_rows', + type: 'POST', + data: { row_ids: history_to_delete.join(',') }, + async: true, + success: function (data) { + var msg = "History deleted"; + showMsg(msg, false, true, 2000); + } }); history_table.draw(); }); diff --git a/data/interfaces/default/info.html b/data/interfaces/default/info.html index ed7b26ad..32c962eb 100644 --- a/data/interfaces/default/info.html +++ b/data/interfaces/default/info.html @@ -721,17 +721,15 @@ DOCUMENTATION :: END $('#deleteCount').text(history_to_delete.length); $('#confirm-modal-delete').modal(); $('#confirm-modal-delete').one('click', '#confirm-delete', function () { - history_to_delete.forEach(function (row, idx) { - $.ajax({ - url: 'delete_history_rows', - type: 'POST', - data: { row_id: row }, - async: true, - success: function (data) { - var msg = "History deleted"; - showMsg(msg, false, true, 2000); - } - }); + $.ajax({ + url: 'delete_history_rows', + type: 'POST', + data: { row_ids: history_to_delete.join(',') }, + async: true, + success: function (data) { + var msg = "History deleted"; + showMsg(msg, false, true, 2000); + } }); history_table.draw(); }); diff --git a/data/interfaces/default/js/tables/history_table.js b/data/interfaces/default/js/tables/history_table.js index a9552dab..c3be6f33 100644 --- a/data/interfaces/default/js/tables/history_table.js +++ b/data/interfaces/default/js/tables/history_table.js @@ -36,10 +36,10 @@ history_table_options = { "targets": [0], "data": null, "createdCell": function (td, cellData, rowData, row, col) { - if (rowData['id'] === null) { + if (rowData['row_id'] === null) { $(td).html(''); } else { - $(td).html(''); + $(td).html(''); } }, "width": "5%", @@ -317,19 +317,19 @@ history_table_options = { "rowCallback": function (row, rowData, rowIndex) { if (rowData['group_count'] == 1) { // if no grouped rows simply toggle the delete button - if ($.inArray(rowData['id'], history_to_delete) !== -1) { - $(row).find('button[data-id="' + rowData['id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + if ($.inArray(rowData['row_id'], history_to_delete) !== -1) { + $(row).find('button[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); } - } else if (rowData['id'] !== null) { + } else if (rowData['row_id'] !== null) { // if grouped rows // toggle the parent button to danger - $(row).find('button[data-id="' + rowData['id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + $(row).find('button[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); // check if any child rows are not selected var group_ids = rowData['group_ids'].split(',').map(Number); group_ids.forEach(function (id) { var index = $.inArray(id, history_to_delete); if (index == -1) { - $(row).find('button[data-id="' + rowData['id'] + '"]').addClass('btn-warning').removeClass('btn-danger'); + $(row).find('button[data-id="' + rowData['row_id'] + '"]').addClass('btn-warning').removeClass('btn-danger'); } }); } @@ -353,7 +353,7 @@ $('.history_table').on('click', '> tbody > tr > td.modal-control', function () { var rowData = row.data(); $.get('get_stream_data', { - row_id: rowData['id'], + row_id: rowData['row_id'], session_key: rowData['session_key'], user: rowData['friendly_name'] }).then(function (jqXHR) { @@ -382,9 +382,9 @@ $('.history_table').on('click', '> tbody > tr > td.delete-control > button', fun if (rowData['group_count'] == 1) { // if no grouped rows simply add or remove row from history_to_delete - var index = $.inArray(rowData['id'], history_to_delete); + var index = $.inArray(rowData['row_id'], history_to_delete); if (index === -1) { - history_to_delete.push(rowData['id']); + history_to_delete.push(rowData['row_id']); } else { history_to_delete.splice(index, 1); } @@ -549,7 +549,7 @@ function createChildTable(row, rowData) { var childRowData = childRow.data(); $.get('get_stream_data', { - row_id: childRowData['id'], + row_id: childRowData['row_id'], user: childRowData['friendly_name'] }).then(function (jqXHR) { $("#info-modal").html(jqXHR); @@ -576,9 +576,9 @@ function createChildTable(row, rowData) { var childRowData = childRow.data(); // add or remove row from history_to_delete - var index = $.inArray(childRowData['id'], history_to_delete); + var index = $.inArray(childRowData['row_id'], history_to_delete); if (index === -1) { - history_to_delete.push(childRowData['id']); + history_to_delete.push(childRowData['row_id']); } else { history_to_delete.splice(index, 1); } diff --git a/data/interfaces/default/js/tables/history_table_modal.js b/data/interfaces/default/js/tables/history_table_modal.js index 575e91cd..69030b3a 100644 --- a/data/interfaces/default/js/tables/history_table_modal.js +++ b/data/interfaces/default/js/tables/history_table_modal.js @@ -169,7 +169,7 @@ $('.history_table').on('click', 'td.modal-control', function () { function showStreamDetails() { $.ajax({ url: 'get_stream_data', - data: { row_id: rowData['id'], user: rowData['friendly_name'] }, + data: { row_id: rowData['row_id'], user: rowData['friendly_name'] }, cache: false, async: true, complete: function (xhr, status) { diff --git a/data/interfaces/default/js/tables/libraries.js b/data/interfaces/default/js/tables/libraries.js index 240670cc..34239c3d 100644 --- a/data/interfaces/default/js/tables/libraries.js +++ b/data/interfaces/default/js/tables/libraries.js @@ -27,8 +27,8 @@ libraries_list_table_options = { "data": null, "createdCell": function (td, cellData, rowData, row, col) { $(td).html('
' + - ' ' + - '   ' + + ' ' + + '   ' + ' ' + '
'); }, @@ -41,14 +41,16 @@ libraries_list_table_options = { "targets": [1], "data": "library_thumb", "createdCell": function (td, cellData, rowData, row, col) { + var inactive = ''; + if (!rowData['is_active']) { inactive = ''; } if (cellData !== null && cellData !== '') { if (rowData['library_thumb'].substring(0, 4) == "http") { - $(td).html('
'); + $(td).html('
' + inactive + '
'); } else { - $(td).html('
'); + $(td).html('
' + inactive + '
'); } } else { - $(td).html('
'); + $(td).html('
' + inactive + '
'); } }, "orderable": false, @@ -61,8 +63,8 @@ libraries_list_table_options = { "data": "section_name", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { - $(td).html('
' + - '' + cellData + '' + + $(td).html('
' + + '' + cellData + '' + '
'); } else { $(td).html('n/a'); @@ -232,11 +234,11 @@ libraries_list_table_options = { showMsg(msg, false, false, 0) }, "rowCallback": function (row, rowData) { - if ($.inArray(rowData['section_id'], libraries_to_delete) !== -1) { - $(row).find('button.delete-library[data-id="' + rowData['section_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + if ($.inArray(rowData['row_id'], libraries_to_delete) !== -1) { + $(row).find('button.delete-library[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); } - if ($.inArray(rowData['section_id'], libraries_to_purge) !== -1) { - $(row).find('button.purge-library[data-id="' + rowData['section_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + if ($.inArray(rowData['row_id'], libraries_to_purge) !== -1) { + $(row).find('button.purge-library[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); } } } @@ -277,11 +279,11 @@ $('#libraries_list_table').on('click', 'td.edit-control > .edit-library-toggles var row = libraries_list_table.row(tr); var rowData = row.data(); - var index_delete = $.inArray(rowData['section_id'], libraries_to_delete); - var index_purge = $.inArray(rowData['section_id'], libraries_to_purge); + var index_delete = $.inArray(rowData['row_id'], libraries_to_delete); + var index_purge = $.inArray(rowData['row_id'], libraries_to_purge); if (index_delete === -1) { - libraries_to_delete.push(rowData['section_id']); + libraries_to_delete.push(rowData['row_id']); if (index_purge === -1) { tr.find('button.purge-library').click(); } @@ -300,11 +302,11 @@ $('#libraries_list_table').on('click', 'td.edit-control > .edit-library-toggles var row = libraries_list_table.row(tr); var rowData = row.data(); - var index_delete = $.inArray(rowData['section_id'], libraries_to_delete); - var index_purge = $.inArray(rowData['section_id'], libraries_to_purge); + var index_delete = $.inArray(rowData['row_id'], libraries_to_delete); + var index_purge = $.inArray(rowData['row_id'], libraries_to_purge); if (index_purge === -1) { - libraries_to_purge.push(rowData['section_id']); + libraries_to_purge.push(rowData['row_id']); } else { libraries_to_purge.splice(index_purge, 1); if (index_delete != -1) { diff --git a/data/interfaces/default/js/tables/user_ips.js b/data/interfaces/default/js/tables/user_ips.js index e73c7635..084b0378 100644 --- a/data/interfaces/default/js/tables/user_ips.js +++ b/data/interfaces/default/js/tables/user_ips.js @@ -167,7 +167,7 @@ $('.user_ip_table').on('click', 'td.modal-control', function () { function showStreamDetails() { $.ajax({ url: 'get_stream_data', - data: { row_id: rowData['id'], user: rowData['friendly_name'] }, + data: { row_id: rowData['history_row_id'], user: rowData['friendly_name'] }, cache: false, async: true, complete: function (xhr, status) { diff --git a/data/interfaces/default/js/tables/users.js b/data/interfaces/default/js/tables/users.js index fdbc0449..15c64fbc 100644 --- a/data/interfaces/default/js/tables/users.js +++ b/data/interfaces/default/js/tables/users.js @@ -44,8 +44,8 @@ users_list_table_options = { "data": null, "createdCell": function (td, cellData, rowData, row, col) { $(td).html('
' + - ' ' + - '   ' + + ' ' + + '   ' + ' ' + ' ' + '
'); @@ -59,10 +59,12 @@ users_list_table_options = { "targets": [1], "data": "user_thumb", "createdCell": function (td, cellData, rowData, row, col) { + var inactive = ''; + if (!rowData['is_active']) { inactive = ''; } if (cellData === '') { - $(td).html('
'); + $(td).html('
' + inactive + '
'); } else { - $(td).html('
'); + $(td).html('
' + inactive + '
'); } }, "orderable": false, @@ -75,7 +77,7 @@ users_list_table_options = { "data": "friendly_name", "createdCell": function (td, cellData, rowData, row, col) { if (cellData !== null && cellData !== '') { - $(td).html('
' + + $(td).html('
' + '' + cellData + '' + '' + '
'); @@ -254,10 +256,10 @@ users_list_table_options = { }, "rowCallback": function (row, rowData) { if ($.inArray(rowData['user_id'], users_to_delete) !== -1) { - $(row).find('button.delete-user[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + $(row).find('button.delete-user[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); } if ($.inArray(rowData['user_id'], users_to_purge) !== -1) { - $(row).find('button.purge-user[data-id="' + rowData['user_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + $(row).find('button.purge-user[data-id="' + rowData['row_id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); } } } @@ -268,7 +270,7 @@ $('#users_list_table').on('click', 'td.modal-control', function () { var rowData = row.data(); $.get('get_stream_data', { - row_id: rowData['id'], + row_id: rowData['history_row_id'], user: rowData['friendly_name'] }).then(function (jqXHR) { $("#info-modal").html(jqXHR); @@ -326,11 +328,11 @@ $('#users_list_table').on('click', 'td.edit-control > .edit-user-toggles > butto var row = users_list_table.row(tr); var rowData = row.data(); - var index_delete = $.inArray(rowData['user_id'], users_to_delete); - var index_purge = $.inArray(rowData['user_id'], users_to_purge); + var index_delete = $.inArray(rowData['row_id'], users_to_delete); + var index_purge = $.inArray(rowData['row_id'], users_to_purge); if (index_delete === -1) { - users_to_delete.push(rowData['user_id']); + users_to_delete.push(rowData['row_id']); if (index_purge === -1) { tr.find('button.purge-user').click(); } @@ -349,11 +351,11 @@ $('#users_list_table').on('click', 'td.edit-control > .edit-user-toggles > butto var row = users_list_table.row(tr); var rowData = row.data(); - var index_delete = $.inArray(rowData['user_id'], users_to_delete); - var index_purge = $.inArray(rowData['user_id'], users_to_purge); + var index_delete = $.inArray(rowData['row_id'], users_to_delete); + var index_purge = $.inArray(rowData['row_id'], users_to_purge); if (index_purge === -1) { - users_to_purge.push(rowData['user_id']); + users_to_purge.push(rowData['row_id']); } else { users_to_purge.splice(index_purge, 1); if (index_delete != -1) { diff --git a/data/interfaces/default/libraries.html b/data/interfaces/default/libraries.html index 4595dce4..f4983904 100644 --- a/data/interfaces/default/libraries.html +++ b/data/interfaces/default/libraries.html @@ -116,14 +116,14 @@ }); if (libraries_to_delete.length > 0) { - $('#libraries-to-delete').prepend('

Are you REALLY sure you want to delete the following libraries:

') + $('#libraries-to-delete').prepend('

Are you REALLY sure you want to delete the following libraries:

'); for (var i = 0; i < libraries_to_delete.length; i++) { $('#libraries-to-delete').append('
  • ' + $('div[data-id=' + libraries_to_delete[i] + ']').text() + '
  • '); } } if (libraries_to_purge.length > 0) { - $('#libraries-to-purge').prepend('

    Are you REALLY sure you want to purge all history for the following libraries:

    ') + $('#libraries-to-purge').prepend('

    Are you REALLY sure you want to purge all history for the following libraries:

    '); for (var i = 0; i < libraries_to_purge.length; i++) { $('#libraries-to-purge').append('
  • ' + $('div[data-id=' + libraries_to_purge[i] + ']').text() + '
  • '); } @@ -131,31 +131,27 @@ $('#confirm-modal-delete').modal(); $('#confirm-modal-delete').one('click', '#confirm-delete', function () { - libraries_to_delete.forEach(function(row, idx) { - $.ajax({ - url: 'delete_library', - type: 'POST', - data: { section_id: row }, - cache: false, - async: true, - success: function (data) { - var msg = "Library deleted"; - showMsg(msg, false, true, 2000); - } - }); + $.ajax({ + url: 'delete_library', + type: 'POST', + data: { row_ids: libraries_to_delete.join(',') }, + cache: false, + async: true, + success: function (data) { + var msg = "Library deleted"; + showMsg(msg, false, true, 2000); + } }); - libraries_to_purge.forEach(function(row, idx) { - $.ajax({ - url: 'delete_all_library_history', - type: 'POST', - data: { section_id: row }, - cache: false, - async: true, - success: function (data) { - var msg = "Library history purged"; - showMsg(msg, false, true, 2000); - } - }); + $.ajax({ + url: 'delete_all_library_history', + type: 'POST', + data: { row_ids: libraries_to_purge.join(',') }, + cache: false, + async: true, + success: function (data) { + var msg = "Library history purged"; + showMsg(msg, false, true, 2000); + } }); libraries_list_table.draw(); }); @@ -188,7 +184,7 @@ complete: function (xhr, status) { var result = $.parseJSON(xhr.responseText); var msg = result.message; - if (result.result == 'success') { + if (result.result === 'success') { showMsg(' ' + msg, false, true, 2000, false); libraries_list_table.draw(); } else { diff --git a/data/interfaces/default/library.html b/data/interfaces/default/library.html index fb57cda4..bd86c04b 100644 --- a/data/interfaces/default/library.html +++ b/data/interfaces/default/library.html @@ -62,9 +62,21 @@ DOCUMENTATION :: END