Fix the way the IP address modal works.

Allow IP address info modal on history page.
Some minor styling changes to improve layout of settings on mobile.
This commit is contained in:
Tim 2015-08-04 01:06:56 +02:00
parent b68a7956c3
commit c02b7a0079
7 changed files with 148 additions and 71 deletions

View file

@ -37,6 +37,8 @@
</table> </table>
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal"> <div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
</div> </div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div>
</div> </div>
</div> </div>
</%def> </%def>

View file

@ -0,0 +1,69 @@
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title" id="myModalLabel">
% if data:
<strong><span id="modal_header_ip_address">
<i class="fa fa-spin fa-refresh"></i>&nbspLoading Details...
</span></strong>
% else:
<i class="fa fa-exclamation-circle"></i>&nbspInvalid IP Address</span></strong>
% endif
</h4>
</div>
<div class="modal-body" id="modal-text">
<div class="col-md-6">
<h4><strong>Location Details</strong></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="col-md-6">
<h4><strong>Connection Details</strong></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>
% if data:
<script>
function getUserLocation(ip_address) {
$.ajax({
url: 'http://ip-api.com/json/' + ip_address,
cache: true,
async: true,
type: 'GET',
dataType: 'json',
error: function(){
$('#modal_header_ip_address').html("Request failed. Server may be too busy.");
},
success: function(data) {
$('#modal_header_ip_address').html("IP Address: " + 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);
},
timeout: 5000
});
}
getUserLocation('${data}');
</script>
% endif

View file

@ -32,7 +32,6 @@ history_table_options = {
"data":"date", "data":"date",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (rowData['stopped'] === null) { if (rowData['stopped'] === null) {
$(td).addClass('currentlyWatching');
$(td).html('Currently watching...'); $(td).html('Currently watching...');
} else { } else {
$(td).html(moment(cellData,"X").format(date_format)); $(td).html(moment(cellData,"X").format(date_format));
@ -71,11 +70,21 @@ history_table_options = {
"targets": [3], "targets": [3],
"data":"ip_address", "data":"ip_address",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if ((cellData == '') || (cellData == '0')) { if (cellData) {
if (isPrivateIP(cellData)) {
if (cellData != '') {
$(td).html(cellData);
} else {
$(td).html('n/a');
}
} else {
$(td).html('<a href="javascript:void(0)" data-toggle="modal" data-target="#ip-info-modal"><i class="fa fa-map-marker"></i>&nbsp' + cellData +'</a>');
}
} else {
$(td).html('n/a'); $(td).html('n/a');
} }
}, },
"className": "no-wrap hidden-xs" "className": "no-wrap hidden-xs modal-control-ip"
}, },
{ {
"targets": [4], "targets": [4],
@ -99,8 +108,12 @@ history_table_options = {
{ {
"targets": [5], "targets": [5],
"data":"started", "data":"started",
"render": function ( data, type, full ) { "createdCell": function (td, cellData, rowData, row, col) {
return moment(data, "X").format(time_format); if (cellData === null) {
$(td).html('n/a');
} else {
$(td).html(moment(cellData,"X").format(time_format));
}
}, },
"searchable": false, "searchable": false,
"className": "no-wrap hidden-sm hidden-xs" "className": "no-wrap hidden-sm hidden-xs"
@ -121,11 +134,11 @@ history_table_options = {
{ {
"targets": [7], "targets": [7],
"data":"stopped", "data":"stopped",
"render": function ( data, type, full ) { "createdCell": function (td, cellData, rowData, row, col) {
if (data !== null) { if (cellData === null) {
return moment(data, "X").format(time_format); $(td).html('n/a');
} else { } else {
return data; $(td).html(moment(cellData,"X").format(time_format));
} }
}, },
"searchable": false, "searchable": false,
@ -193,4 +206,27 @@ $('#history_table').on('click', 'td.modal-control', function () {
}); });
} }
showStreamDetails(); showStreamDetails();
});
$('#history_table').on('click', 'td.modal-control-ip', function () {
var tr = $(this).parents('tr');
var row = history_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']);
}); });

View file

@ -92,22 +92,11 @@ $('#user_ip_table').on('click', 'td.modal-control', function () {
return "n/a" return "n/a"
} else { } else {
$.ajax({ $.ajax({
url: 'http://ip-api.com/json/' + ip_address, url: 'get_ip_address_details',
cache: true, data: {ip_address: ip_address},
async: true, async: true,
type: 'GET', complete: function(xhr, status) {
dataType: 'json', $("#ip-info-modal").html(xhr.responseText);
success: function(data) {
$('#modal_header_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);
} }
}); });
} }

View file

@ -64,7 +64,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="date_format">Date Format</label> <label for="date_format">Date Format</label>
<div class="row"> <div class="row">
<div class="col-xs-4"> <div class="col-md-4">
<input type="text" class="form-control" id="date_format" name="date_format" value="${config['date_format']}" data-parsley-trigger="change" required> <input type="text" class="form-control" id="date_format" name="date_format" value="${config['date_format']}" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -73,7 +73,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="date_format">Time Format</label> <label for="date_format">Time Format</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" id="time_format" name="time_format" value="${config['time_format']}" data-parsley-trigger="change" required> <input type="text" class="form-control" id="time_format" name="time_format" value="${config['time_format']}" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -89,7 +89,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="http_host">HTTP Host</label> <label for="http_host">HTTP Host</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<input type="text" class="form-control" id="http_host" name="http_host" value="${config['http_host']}" data-parsley-trigger="change" required> <input type="text" class="form-control" id="http_host" name="http_host" value="${config['http_host']}" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -98,7 +98,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="http_port">HTTP Port</label> <label for="http_port">HTTP Port</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="http_port" name="http_port" value="${config['http_port']}" data-parsley-trigger="change" required> <input type="text" class="form-control" data-parsley-type="integer" id="http_port" name="http_port" value="${config['http_port']}" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -138,7 +138,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="http_username">HTTP Username</label> <label for="http_username">HTTP Username</label>
<div class="row"> <div class="row">
<div class="col-xs-4"> <div class="col-md-4">
<input type="text" class="form-control" id="http_username" name="http_username" value="${config['http_username']}" size="30"> <input type="text" class="form-control" id="http_username" name="http_username" value="${config['http_username']}" size="30">
</div> </div>
</div> </div>
@ -147,7 +147,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="http_password">HTTP Password</label> <label for="http_password">HTTP Password</label>
<div class="row"> <div class="row">
<div class="col-xs-4"> <div class="col-md-4">
<input type="password" class="form-control" id="http_password" name="http_password" value="${config['http_password']}" size="30"> <input type="password" class="form-control" id="http_password" name="http_password" value="${config['http_password']}" size="30">
</div> </div>
</div> </div>
@ -167,7 +167,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div id="apioptions" class="form-group"> <div id="apioptions" class="form-group">
<label for="api_key">API key</label> <label for="api_key">API key</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<div class="input-group"> <div class="input-group">
<input class="form-control" type="text" name="api_key" id="api_key" value="${config['api_key']}" size="20"> <input class="form-control" type="text" name="api_key" id="api_key" value="${config['api_key']}" size="20">
<span class="input-group-btn"> <span class="input-group-btn">
@ -189,7 +189,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group has-feedback" id="pms-ip-group"> <div class="form-group has-feedback" id="pms-ip-group">
<label for="pms_ip">Plex IP or Hostname</label> <label for="pms_ip">Plex IP or Hostname</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<input type="text" class="pms-settings form-control" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30" data-parsley-trigger="change" aria-describedby="server-verified" required> <input type="text" class="pms-settings form-control" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30" data-parsley-trigger="change" aria-describedby="server-verified" required>
<span class="form-control-feedback" id="pms-verify" aria-hidden="true" style="display: none;"></span> <span class="form-control-feedback" id="pms-verify" aria-hidden="true" style="display: none;"></span>
</div> </div>
@ -199,7 +199,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="pms_port">Plex Port</label> <label for="pms_port">Plex Port</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input data-parsley-type="integer" class="pms-settings form-control" type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" data-parsley-trigger="change" required> <input data-parsley-type="integer" class="pms-settings form-control" type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -229,7 +229,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="pms_token">PMS Token</label> <label for="pms_token">PMS Token</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" id="pms_token" name="pms_token" value="${config['pms_token']}" data-parsley-trigger="change" required> <input type="text" class="form-control" id="pms_token" name="pms_token" value="${config['pms_token']}" data-parsley-trigger="change" required>
<span class="input-group-btn"> <span class="input-group-btn">
@ -247,7 +247,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="refresh_users_interval">User list Refresh Interval</label> <label for="refresh_users_interval">User list Refresh Interval</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="refresh_users_interval" name="refresh_users_interval" value="${config['refresh_users_interval']}" size="5" data-parsley-range="[1,24]" data-parsley-trigger="change" required> <input type="text" class="form-control" data-parsley-type="integer" id="refresh_users_interval" name="refresh_users_interval" value="${config['refresh_users_interval']}" size="5" data-parsley-range="[1,24]" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -281,7 +281,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="pms_logs_folder">Logs Folder</label> <label for="pms_logs_folder">Logs Folder</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<input type="text" class="form-control" id="pms_logs_folder" name="pms_logs_folder" value="${config['pms_logs_folder']}" size="30" data-parsley-trigger="change"> <input type="text" class="form-control" id="pms_logs_folder" name="pms_logs_folder" value="${config['pms_logs_folder']}" size="30" data-parsley-trigger="change">
</div> </div>
</div> </div>
@ -304,7 +304,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="monitoring_interval">Monitoring Interval</label> <label for="monitoring_interval">Monitoring Interval</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required> <input type="text" class="form-control" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -323,7 +323,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="monitoring_interval">Ignore Interval</label> <label for="monitoring_interval">Ignore Interval</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="0" data-parsley-trigger="change" required> <input type="text" class="form-control" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="0" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -374,7 +374,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="notify_watched_percent">Watched Percent</label> <label for="notify_watched_percent">Watched Percent</label>
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" required> <input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" required>
</div> </div>
</div> </div>
@ -624,7 +624,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="pms_username">PMS Username</label> <label for="pms_username">PMS Username</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<input type="text" class="form-control" id="pms_username" name="pms_username" size="30"> <input type="text" class="form-control" id="pms_username" name="pms_username" size="30">
</div> </div>
</div> </div>
@ -633,7 +633,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="form-group"> <div class="form-group">
<label for="pms_password">PMS Password</label> <label for="pms_password">PMS Password</label>
<div class="row"> <div class="row">
<div class="col-xs-6"> <div class="col-md-6">
<input type="password" class="form-control" id="pms_password" name="pms_password" size="30"> <input type="password" class="form-control" id="pms_password" name="pms_password" size="30">
</div> </div>
</div> </div>

View file

@ -127,36 +127,6 @@ from plexpy import helpers
</table> </table>
</div> </div>
<div id="ip-info-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal"> <div id="ip-info-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title" id="myModalLabel">IP Address: <strong><span id="modal_header_ip_address"></span></strong></h4>
</div>
<div class="modal-body" id="modal-text">
<div class="col-md-6">
<h4><strong>Location Details</strong></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="col-md-6">
<h4><strong>Connection Details</strong></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>
</div> </div>
</div> </div>

View file

@ -208,6 +208,17 @@ class WebInterface(object):
return serve_template(templatename="stream_data.html", title="Stream Data", data=stream_data, user=user) return serve_template(templatename="stream_data.html", title="Stream Data", data=stream_data, user=user)
@cherrypy.expose
def get_ip_address_details(self, ip_address=None, **kwargs):
import socket
try:
socket.inet_aton(ip_address)
except socket.error:
ip_address = None
return serve_template(templatename="ip_address_modal.html", title="IP Address Details", data=ip_address)
@cherrypy.expose @cherrypy.expose
def get_user_list(self, **kwargs): def get_user_list(self, **kwargs):