From d6c21e173dd96b0435c249d47e5d811b4b416d0b Mon Sep 17 00:00:00 2001 From: Jonathan Wong Date: Tue, 15 Sep 2015 23:35:07 -0700 Subject: [PATCH] Update history table to show grouped items --- data/interfaces/default/css/plexpy.css | 36 ++ .../default/js/tables/history_table.js | 311 ++++++++++++++++-- 2 files changed, 321 insertions(+), 26 deletions(-) diff --git a/data/interfaces/default/css/plexpy.css b/data/interfaces/default/css/plexpy.css index ff44dbea..2842814e 100644 --- a/data/interfaces/default/css/plexpy.css +++ b/data/interfaces/default/css/plexpy.css @@ -2350,4 +2350,40 @@ a .home-platforms-instance-list-oval:hover, .dashboard-instance { width: 100%; } +} + +table.display tr.shown + tr div.slider { + display: none; +} +table.display tr.shown + tr > td { + padding-top: 0; + padding-bottom: 0; +} +table.display tr.shown + tr:hover { + background-color: rgba(255,255,255,0); +} +table.display tr.shown + tr:hover a, +table.display tr.shown + tr td:hover a, +table.display tr.shown + tr .pagination > .active > a, +table.display tr.shown + tr .pagination > .active > a:hover { + color: #fff; +} +table.display tr.shown + tr table[id^='history_child'] td:hover a { + color: #F9AA03; +} +table.display tr.shown + tr .pagination > .disabled > a { + color: #444444; +} +table.display tr.shown + tr .pagination > li > a:hover { + color: #23527c; +} +table[id^='history_child'] { + margin-top: 0; + margin-left: -4px; + opacity: .6; +} +table[id^='history_child'] thead th { + line-height: 0; + height: 0 !important; + overflow: hidden; } \ No newline at end of file diff --git a/data/interfaces/default/js/tables/history_table.js b/data/interfaces/default/js/tables/history_table.js index 1cccbf9b..dcd94933 100644 --- a/data/interfaces/default/js/tables/history_table.js +++ b/data/interfaces/default/js/tables/history_table.js @@ -46,13 +46,17 @@ history_table_options = { "createdCell": function (td, cellData, rowData, row, col) { if (rowData['stopped'] === null) { $(td).html('Currently watching...'); + } else if (rowData['group_count'] > 1) { + date = moment(cellData, "X").format(date_format); + expand_history = ''; + $(td).html('
' + expand_history + ' ' + date + '
'); } else { - $(td).html(moment(cellData,"X").format(date_format)); + $(td).html(moment(cellData, "X").format(date_format)); } }, "searchable": false, "width": "8%", - "className": "no-wrap" + "className": "no-wrap expand-history" }, { "targets": [2], @@ -83,7 +87,8 @@ history_table_options = { $(td).html('n/a'); } } else { - $(td).html(' ' + cellData + ''); + external_ip = ''; + $(td).html(''+ external_ip + cellData + ''); } } else { $(td).html('n/a'); @@ -105,7 +110,7 @@ history_table_options = { } else if (rowData['video_decision'] === 'direct play' || rowData['video_decision'] === '') { transcode_dec = ''; } - $(td).html('
' + transcode_dec + ' ' + cellData + '
'); + $(td).html('
' + transcode_dec + ' ' + cellData + '
'); } }, "width": "15%", @@ -121,16 +126,16 @@ history_table_options = { if (rowData['media_type'] === 'movie') { media_type = ''; thumb_popover = '' + cellData + ' (' + rowData['year'] + ')' - $(td).html('
' + media_type + ' ' + thumb_popover + '
'); + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else if (rowData['media_type'] === 'episode') { media_type = ''; thumb_popover = '' + cellData + ' \ (S' + rowData['parent_media_index'] + '· E' + rowData['media_index'] + ')' - $(td).html('
' + media_type + ' ' + thumb_popover + '
'); + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else if (rowData['media_type'] === 'track') { media_type = ''; thumb_popover = '' + cellData + ' (' + rowData['parent_title'] + ')' - $(td).html('
' + media_type + ' ' + thumb_popover + '
'); + $(td).html('
' + media_type + ' ' + thumb_popover + '
'); } else { $(td).html('' + cellData + ''); } @@ -155,7 +160,7 @@ history_table_options = { { "targets": [7], "data":"paused_counter", - "render": function ( data, type, full ) { + "render": function (data, type, full) { if (data !== null) { return Math.round(moment.duration(data, 'seconds').as('minutes')) + ' mins'; } else { @@ -183,7 +188,7 @@ history_table_options = { { "targets": [9], "data":"duration", - "render": function ( data, type, full ) { + "render": function (data, type, full) { if (data !== null) { return Math.round(moment.duration(data, 'seconds').as('minutes')) + ' mins'; } else { @@ -197,7 +202,7 @@ history_table_options = { { "targets": [10], "data":"percent_complete", - "render": function ( data, type, full ) { + "render": function (data, type, full) { if (data > 80) { return '' } else if (data > 40) { @@ -218,6 +223,8 @@ history_table_options = { $('#ajaxMsg').fadeOut(); // Create the tooltips. + $('.expand-history-tooltip').tooltip({ container: 'body' }); + $('.external-ip-tooltip').tooltip(); $('.transcode-tooltip').tooltip(); $('.media-type-tooltip').tooltip(); $('.watched-tooltip').tooltip(); @@ -231,24 +238,57 @@ history_table_options = { }); if ($('#row-edit-mode').hasClass('active')) { - $('.delete-control').each(function() { + $('.delete-control').each(function () { $(this).removeClass('hidden'); }); } + + history_table.rows().every(function () { + var rowData = this.data(); + if (rowData['group_count'] != 1 && rowData['group_start_id'] in history_child_table) { + // if grouped row and a child table was already created + this.child(childTableFormat(rowData)).show(); + createChildTable(this, rowData) + } + }); }, - "preDrawCallback": function(settings) { + "preDrawCallback": function (settings) { var msg = "
 Fetching rows...
"; showMsg(msg, false, false, 0) }, - "rowCallback": function (row, rowData) { - if ($.inArray(rowData['id'], history_to_delete) !== -1) { + "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'); + } + } else { + // if grouped rows + // toggle the parent button to danger $(row).find('button[data-id="' + rowData['id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + // check if any child rows are not selected + for (var i = rowData['group_start_id']; i <= rowData['id']; i++) { + var index = $.inArray(i, history_to_delete); + if (index == -1) { + // if any child row is not selected, toggle parent button to warning + $(row).find('button[data-id="' + rowData['id'] + '"]').toggleClass('btn-warning').toggleClass('btn-danger'); + break; + } + } } + + if (rowData['group_count'] != 1 && rowData['group_start_id'] in history_child_table) { + // if grouped row and a child table was already created + $(row).addClass('shown') + history_table.row(row).child(childTableFormat(rowData)).show(); + } + } } -$('#history_table').on('click', 'td.modal-control', function () { - var tr = $(this).parents('tr'); +// Parent table platform modal +$('#history_table').on('click', '> tbody > tr > td.modal-control', function () { + var tr = $(this).closest('tr'); var row = history_table.row( tr ); var rowData = row.data(); @@ -266,8 +306,9 @@ $('#history_table').on('click', 'td.modal-control', function () { showStreamDetails(); }); -$('#history_table').on('click', 'td.modal-control-ip', function () { - var tr = $(this).parents('tr'); +// Parent table ip address modal +$('#history_table').on('click', '> tbody > tr > td.modal-control-ip', function () { + var tr = $(this).closest('tr'); var row = history_table.row( tr ); var rowData = row.data(); @@ -288,16 +329,234 @@ $('#history_table').on('click', 'td.modal-control-ip', function () { getUserLocation(rowData['ip_address']); }); -$('#history_table').on('click', 'td.delete-control > button', function () { - var tr = $(this).parents('tr'); +// Parent table delete mode +$('#history_table').on('click', '> tbody > tr > td.delete-control > button', function () { + var tr = $(this).closest('tr'); var row = history_table.row( tr ); var rowData = row.data(); - var index = $.inArray(rowData['id'], history_to_delete); - if (index === -1) { - history_to_delete.push(rowData['id']); + 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); + if (index === -1) { + history_to_delete.push(rowData['id']); + } else { + history_to_delete.splice(index, 1); + } + $(this).toggleClass('btn-warning').toggleClass('btn-danger'); } else { - history_to_delete.splice(index, 1); + // if grouped rows + if ($(this).hasClass('btn-warning')) { + // add all grouped rows to history_to_delete + for (var i = rowData['group_start_id']; i <= rowData['id']; i++) { + var index = $.inArray(i, history_to_delete); + if (index == -1) { + history_to_delete.push(i); + } + } + $(this).toggleClass('btn-warning').toggleClass('btn-danger'); + if (row.child.isShown()) { + // if child table is visible, toggle all child buttons to danger + tr.next().find('td.delete-control > button.btn-warning').toggleClass('btn-warning').toggleClass('btn-danger'); + } + } else { + // remove all grouped rows to history_to_delete + for (var i = rowData['group_start_id']; i <= rowData['id']; i++) { + var index = $.inArray(i, history_to_delete); + if (index != -1) { + history_to_delete.splice(index, 1); + } + } + $(this).toggleClass('btn-warning').toggleClass('btn-danger'); + if (row.child.isShown()) { + // if child table is visible, toggle all child buttons to warning + tr.next().find('td.delete-control > button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger'); + } + } } - $(this).toggleClass('btn-warning').toggleClass('btn-danger'); -}); \ No newline at end of file +}); + +// Parent table expand detailed history +$('#history_table').on('click', '> tbody > tr > td.expand-history a', function () { + var tr = $(this).closest('tr'); + var row = history_table.row(tr); + var rowData = row.data(); + + if (row.child.isShown()) { + $('div.slider', row.child()).slideUp(function () { + row.child.hide(); + tr.removeClass('shown'); + delete history_child_table[rowData['group_start_id']]; + }); + } else { + tr.addClass('shown'); + row.child(childTableFormat(rowData)).show(); + createChildTable(row, rowData); + } +}); + + +// Initialize the detailed history child table options using the parent table options +function childTableOptions(rowData) { + history_child_options = history_table_options; + // Remove settings that are not necessary + history_child_options.searching = false; + history_child_options.lengthChange = false; + history_child_options.info = false; + history_child_options.pageLength = 10; + history_child_options.bStateSave = false; + history_child_options.ajax = { + "url": "get_history", + type: "post", + data: function (d) { + return { + 'json_data': JSON.stringify(d), + 'grouping': false, + 'group_start_id': rowData['group_start_id'] + }; + } + } + history_child_options.fnDrawCallback = function (settings) { + $('#ajaxMsg').fadeOut(); + + // Create the tooltips. + $('.expand-history-tooltip').tooltip({ container: 'body' }); + $('.external-ip-tooltip').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'); + }); + } + + $(this).closest('div.slider').slideDown(); + } + + return history_child_options; +} + +// Format the detailed history child table +function childTableFormat(rowData) { + return '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
DeleteTimeUserIP AddressPlatformTitleStartedPausedStoppedDuration
' + + '
'; +} + +// Create the detailed history child table +history_child_table = {}; +function createChildTable(row, rowData) { + history_child_options = childTableOptions(rowData); + // initialize the child table + history_child_table[rowData['group_start_id']] = $('#history_child-' + rowData['group_start_id']).DataTable(history_child_options); + + // Set child table column visibility to match parent table + var visibility = history_table.columns().visible(); + for (var i = 0; i < visibility.length; i++) { + if (!(visibility[i])) { history_child_table[rowData['group_start_id']].column(i).visible(visibility[i]); } + } + history_table.on('column-visibility', function (e, settings, colIdx, visibility) { + if (row.child.isShown()) { + history_child_table[rowData['group_start_id']].column(colIdx).visible(visibility); + } + }); + + // Child table platform modal + $('#history_child-' + rowData['group_start_id']).on('click', 'td.modal-control', function () { + var tr = $(this).closest('tr'); + var childRow = history_child_table[rowData['group_start_id']].row(tr); + var childRowData = childRow.data(); + + function showStreamDetails() { + $.ajax({ + url: 'get_stream_data', + data: { row_id: childRowData['id'], user: childRowData['friendly_name'] }, + cache: false, + async: true, + complete: function (xhr, status) { + $("#info-modal").html(xhr.responseText); + } + }); + } + showStreamDetails(); + }); + + // Child table ip address modal + $('#history_child-' + rowData['group_start_id']).on('click', 'td.modal-control-ip', function () { + var tr = $(this).closest('tr'); + var childRow = history_child_table[rowData['group_start_id']].row(tr); + var childRowData = childRow.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(childRowData['ip_address']); + }); + + // Child table delete mode + $('#history_child-' + rowData['group_start_id']).on('click', 'td.delete-control > button', function () { + var tr = $(this).closest('tr'); + var childRow = history_child_table[rowData['group_start_id']].row(tr); + var childRowData = childRow.data(); + + // add or remove row from history_to_delete + var index = $.inArray(childRowData['id'], history_to_delete); + if (index === -1) { + history_to_delete.push(childRowData['id']); + } else { + history_to_delete.splice(index, 1); + } + $(this).toggleClass('btn-warning').toggleClass('btn-danger'); + + tr.parents('tr').prev().find('td.delete-control > button.btn-warning').toggleClass('btn-warning').toggleClass('btn-danger'); + // check if any child rows are not selected + for (var i = rowData['group_start_id']; i <= rowData['id']; i++) { + var index = $.inArray(i, history_to_delete); + if (index == -1) { + // if any child row is not selected, toggle parent button to warning + tr.parents('tr').prev().find('td.delete-control > button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger'); + break; + } + } + }); +} +