We have initial implementation of sync lists (may still be buggy)

To get usernames in sync lists go to Users->Refresh Users.
This commit is contained in:
Tim 2015-07-02 13:04:19 +02:00
parent 6927753db6
commit d2db662e14
7 changed files with 103 additions and 36 deletions

View file

@ -113,6 +113,19 @@ from plexpy import version
</a> </a>
</li> </li>
% endif % endif
% if title=="Synced Items":
<li class="active">
<a href="sync">
<i class="fa fa-cloud-download fa-2x" data-toggle="tooltip" data-placement="bottom" title="Synced Items" id="sync"></i>
</a>
</li>
% else:
<li>
<a href="sync">
<i class="fa fa-cloud-download fa-2x" data-toggle="tooltip" data-placement="bottom" title="Synced Items" id="sync"></i>
</a>
</li>
% endif
% if title=="Log": % if title=="Log":
<li class="active"> <li class="active">
<a href="logs"> <a href="logs">
@ -161,6 +174,9 @@ ${next.body()}
$(document).ready(function() { $(document).ready(function() {
$('#graphs').tooltip(); $('#graphs').tooltip();
}); });
$(document).ready(function() {
$('#sync').tooltip();
});
$(document).ready(function() { $(document).ready(function() {
$('#logs').tooltip(); $('#logs').tooltip();
}); });

View file

@ -57,12 +57,12 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="http_host">HTTP Host</label> <label for="http_host">HTTP Host</label>
<input type="text" id="http_host" name="http_host" value="${config['http_host']}" size="30"> <input type="text" id="http_host" name="http_host" value="${config['http_host']}" size="30" required="required">
<p class="help-block">e.g. localhost or an IP, such as 0.0.0.0</p> <p class="help-block">e.g. localhost or an IP, such as 0.0.0.0</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="http_port">HTTP Port</label> <label for="http_port">HTTP Port</label>
<input type="text" id="http_port" name="http_port" value="${config['http_port']}" size="10"> <input type="text" id="http_port" name="http_port" value="${config['http_port']}" size="10" required="required">
<p class="help-block">Port to bind web server to. Note that ports below 1024 may require root.</p> <p class="help-block">Port to bind web server to. Note that ports below 1024 may require root.</p>
</div> </div>
<div class="checkbox"> <div class="checkbox">
@ -136,12 +136,12 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="date_format">Date Format</label> <label for="date_format">Date Format</label>
<input type="text" id="date_format" name="date_format" value="${config['date_format']}" size="30"> <input type="text" id="date_format" name="date_format" value="${config['date_format']}" size="30" required="required">
<p class="help-block">Set your preferred date format. <a href="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p> <p class="help-block">Set your preferred date format. <a href="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="date_format">Time Format</label> <label for="date_format">Time Format</label>
<input type="text" id="time_format" name="time_format" value="${config['time_format']}" size="30"> <input type="text" id="time_format" name="time_format" value="${config['time_format']}" size="30" required="required">
<p class="help-block">Set your preferred time format. <a href="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p> <p class="help-block">Set your preferred time format. <a href="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div> </div>
</fieldset> </fieldset>
@ -153,12 +153,12 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="pms_ip">PMS IP</label> <label for="pms_ip">PMS IP</label>
<input type="text" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30"> <input type="text" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30" required="required">
<p class="help-block">IP Address for Plex Media Server.</p> <p class="help-block">IP Address for Plex Media Server.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="pms_port">PMS Port</label> <label for="pms_port">PMS Port</label>
<input type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30"> <input type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" required="required">
<p class="help-block">Port that Plex Media Server is listening on.</p> <p class="help-block">Port that Plex Media Server is listening on.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -176,7 +176,7 @@
<fieldset> <fieldset>
<div class="form-group"> <div class="form-group">
<label for="plexwatch_database">PlexWatch Database</label> <label for="plexwatch_database">PlexWatch Database</label>
<input type="text" id="plexwatch_database" name="plexwatch_database" value="${config['plexwatch_database']}" size="30"> <input type="text" id="plexwatch_database" name="plexwatch_database" value="${config['plexwatch_database']}" size="30" required="required">
<p class="help-block">Full path and file name of your PlexWatch database.</p> <p class="help-block">Full path and file name of your PlexWatch database.</p>
</div> </div>
<div class="checkbox"> <div class="checkbox">
@ -697,12 +697,12 @@
<br/><br/> <br/><br/>
<div class="form-group"> <div class="form-group">
<label for="pms_username">PMS Username</label> <label for="pms_username">PMS Username</label>
<input type="text" id="pms_username" name="pms_username" size="30"> <input type="text" id="pms_username" name="pms_username" size="30" required="required">
<p class="help-block">Username for Plex.tv authentication.</p> <p class="help-block">Username for Plex.tv authentication.</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="pms_password">PMS Password</label> <label for="pms_password">PMS Password</label>
<input type="password" id="pms_password" name="pms_password" size="30"> <input type="password" id="pms_password" name="pms_password" size="30" required="required">
<p class="help-block">Password for Plex.tv authentication.</p> <p class="help-block">Password for Plex.tv authentication.</p>
</div> </div>
</div> </div>

View file

@ -1,12 +1,9 @@
$('#sync_table').dataTable( { sync_table_options = {
"responsive": { "responsive": {
details: false details: false
}, },
"processing": false, "processing": false,
"serverSide": false, "serverSide": false,
"ajax": {
"url": "get_sync"
},
"sPaginationType": "bootstrap", "sPaginationType": "bootstrap",
"order": [ 0, 'desc'], "order": [ 0, 'desc'],
"pageLength": 25, "pageLength": 25,
@ -108,10 +105,5 @@ $('#sync_table').dataTable( {
"drawCallback": function (settings) { "drawCallback": function (settings) {
// Jump to top of page // Jump to top of page
$('html,body').scrollTop(0); $('html,body').scrollTop(0);
$('#ajaxMsg').addClass('success').fadeOut();
},
"preDrawCallback": function(settings) {
$('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>Fetching rows...</div>");
$('#ajaxMsg').addClass('success').fadeIn();
} }
}); }

View file

@ -20,7 +20,7 @@ from plexpy import helpers
<div class="span12"> <div class="span12">
<div class="wellheader-bg"> <div class="wellheader-bg">
<div class="dashboard-wellheader-no-chevron"> <div class="dashboard-wellheader-no-chevron">
<h2><i class="fa fa-book"></i> Synced Items</h2> <h2><i class="fa fa-cloud-download"></i> Synced Items</h2>
</div> </div>
</div> </div>
</div> </div>
@ -62,5 +62,12 @@ from plexpy import helpers
<script src="interfaces/default/js/dataTables.responsive.js"></script> <script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/tables/sync_table.js"></script> <script src="interfaces/default/js/tables/sync_table.js"></script>
<script>
$(document).ready(function() {
sync_table_options.ajax = {
"url": "get_sync"
}
sync_table = $('#sync_table').DataTable(sync_table_options);
});
</script>
</%def> </%def>

View file

@ -49,6 +49,7 @@ from plexpy import helpers
<li class="active"><a href="#profile" data-toggle="tab">Profile</a></li> <li class="active"><a href="#profile" data-toggle="tab">Profile</a></li>
<li><a id="ip-tab-btn" href="#userAddresses" data-toggle="tab">IP Addresses</a></li> <li><a id="ip-tab-btn" href="#userAddresses" data-toggle="tab">IP Addresses</a></li>
<li><a id="history-tab-btn" href="#userHistory" data-toggle="tab">History</a></li> <li><a id="history-tab-btn" href="#userHistory" data-toggle="tab">History</a></li>
<li><a id="sync-tab-btn" href="#userSyncItems" data-toggle="tab">Synced Items</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@ -208,6 +209,40 @@ from plexpy import helpers
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane" id="userSyncItems">
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div class="table-card-back">
<h3>Synced Items for <strong>
<span class="set-username">${data['friendly_name']}</span>
</strong></h3>
</div>
<div class="table-card-back">
<table class="display" id="sync_table" width="100%">
<thead>
<tr>
<th align='left' id="state">State</th>
<th align='left' id="username">Username</th>
<th align='left' id="sync_title">Title</th>
<th align='left' id="type">Type</th>
<th align='left' id="device">Device</th>
<th align='left' id="sync_platform">Platform</th>
<th align='left' id="size">Total Size</th>
<th align='left' id="items">Total Items</th>
<th align='left' id="converted">Converted</th>
<th align='left' id="downloaded">Downloaded</th>
<th align='left' id="sync_percent_complete">Complete</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<footer></footer> <footer></footer>
</%def> </%def>
@ -219,6 +254,7 @@ from plexpy import helpers
<script src="interfaces/default/js/moment-with-locale.js"></script> <script src="interfaces/default/js/moment-with-locale.js"></script>
<script src="interfaces/default/js/tables/history_table.js"></script> <script src="interfaces/default/js/tables/history_table.js"></script>
<script src="interfaces/default/js/tables/user_ips.js"></script> <script src="interfaces/default/js/tables/user_ips.js"></script>
<script src="interfaces/default/js/tables/sync_table.js"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
@ -275,6 +311,17 @@ from plexpy import helpers
user_ip_table = $('#user_ip_table').DataTable(user_ip_table_options); user_ip_table = $('#user_ip_table').DataTable(user_ip_table_options);
}); });
$( "#sync-tab-btn" ).one( "click", function() {
// Build user sync table
sync_table_options.ajax = {
"url": "get_sync",
"data": function(d) {
d.user_id = "${data['user_id']}";
}
}
sync_table = $('#sync_table').DataTable(sync_table_options);
});
// Load edit user modal // Load edit user modal
$("#toggle-edit-user-modal").click(function() { $("#toggle-edit-user-modal").click(function() {
$.ajax({ $.ajax({

View file

@ -284,7 +284,7 @@ class PlexTV(object):
return users_list return users_list
def get_synced_items(self, machine_id=None): def get_synced_items(self, machine_id=None, user_id=None):
sync_list = self.get_plextv_sync_lists(machine_id) sync_list = self.get_plextv_sync_lists(machine_id)
plex_watch = plexwatch.PlexWatch() plex_watch = plexwatch.PlexWatch()
@ -304,9 +304,15 @@ class PlexTV(object):
else: else:
for a in xml_head: for a in xml_head:
client_id = self.get_xml_attr(a, 'id') client_id = self.get_xml_attr(a, 'id')
sync_device = a.getElementsByTagName('Device') sync_device = a.getElementsByTagName('Device')
for device in sync_device: for device in sync_device:
device_user_id = self.get_xml_attr(device, 'userID')
try:
device_username = plex_watch.get_user_details(user_id=device_user_id)['username']
device_friendly_name = plex_watch.get_user_details(user_id=device_user_id)['friendly_name']
except:
device_username = ''
device_friendly_name = ''
device_name = self.get_xml_attr(device, 'name') device_name = self.get_xml_attr(device, 'name')
device_product = self.get_xml_attr(device, 'product') device_product = self.get_xml_attr(device, 'product')
device_product_version = self.get_xml_attr(device, 'productVersion') device_product_version = self.get_xml_attr(device, 'productVersion')
@ -315,13 +321,10 @@ class PlexTV(object):
device_type = self.get_xml_attr(device, 'device') device_type = self.get_xml_attr(device, 'device')
device_model = self.get_xml_attr(device, 'model') device_model = self.get_xml_attr(device, 'model')
device_last_seen = self.get_xml_attr(device, 'lastSeenAt') device_last_seen = self.get_xml_attr(device, 'lastSeenAt')
device_user_id = self.get_xml_attr(device, 'userID')
try: # Filter by user_id
device_username = plex_watch.get_user_details(user_id=device_user_id)['username'] if user_id and user_id != device_user_id:
device_friendly_name = plex_watch.get_user_details(user_id=device_user_id)['friendly_name'] break
except:
device_username = ''
device_friendly_name = ''
for synced in a.getElementsByTagName('SyncItems'): for synced in a.getElementsByTagName('SyncItems'):
sync_item = synced.getElementsByTagName('SyncItem') sync_item = synced.getElementsByTagName('SyncItem')

View file

@ -897,20 +897,22 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("users") raise cherrypy.HTTPRedirect("users")
@cherrypy.expose @cherrypy.expose
def get_sync(self, machine_id='', **kwargs): def get_sync(self, machine_id=None, user_id=None, **kwargs):
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
server_info = pms_connect.get_servers_info() server_info = pms_connect.get_servers_info()
plex_tv = plextv.PlexTV() plex_tv = plextv.PlexTV()
if not machine_id: if not machine_id:
result = plex_tv.get_synced_items(machine_id=server_info[0]['machine_identifier']) result = plex_tv.get_synced_items(machine_id=server_info[0]['machine_identifier'], user_id=user_id)
else: else:
result = plex_tv.get_synced_items(machine_id=machine_id) result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
if result: if result:
cherrypy.response.headers['Content-type'] = 'application/json'
output = {"data": result} output = {"data": result}
return json.dumps(output)
else: else:
logger.warn('Unable to retrieve data.') logger.warn('Unable to retrieve sync data for user.')
output = {"data": []}
cherrypy.response.headers['Content-type'] = 'application/json'
return json.dumps(output)