mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 23:42:37 -07:00
Final clean up
This commit is contained in:
parent
6152a1e913
commit
7f1a08dd04
12 changed files with 63 additions and 150 deletions
|
@ -70,7 +70,6 @@ DOCUMENTATION :: END
|
||||||
%>
|
%>
|
||||||
|
|
||||||
% if data:
|
% if data:
|
||||||
% if data[0]['stat_id']:
|
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
% if any(top_stat['rows'] for top_stat in data):
|
% if any(top_stat['rows'] for top_stat in data):
|
||||||
% for top_stat in data:
|
% for top_stat in data:
|
||||||
|
@ -872,8 +871,4 @@ DOCUMENTATION :: END
|
||||||
</script>
|
</script>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">No stats to show for the selected period.</div><br>
|
<div class="text-muted">No stats to show for the selected period.</div><br>
|
||||||
% endif
|
|
||||||
% else:
|
|
||||||
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
|
|
||||||
</div><br>
|
|
||||||
% endif
|
% endif
|
|
@ -47,6 +47,9 @@ media_info_table_options = {
|
||||||
} else if (rowData['media_type'] === 'album') {
|
} else if (rowData['media_type'] === 'album') {
|
||||||
expand_details = '<span class="expand-media-info-tooltip" data-toggle="tooltip" title="Show Tracks"><i class="fa fa-plus-circle fa-fw"></i></span>';
|
expand_details = '<span class="expand-media-info-tooltip" data-toggle="tooltip" title="Show Tracks"><i class="fa fa-plus-circle fa-fw"></i></span>';
|
||||||
$(td).html('<div><a href="#"><div style="float: left;">' + expand_details + ' ' + date + '</div></a></div>');
|
$(td).html('<div><a href="#"><div style="float: left;">' + expand_details + ' ' + date + '</div></a></div>');
|
||||||
|
} else if (rowData['media_type'] === 'photo' && rowData['parent_rating_key'] == '') {
|
||||||
|
expand_details = '<span class="expand-media-info-tooltip" data-toggle="tooltip" title="Show Photos"><i class="fa fa-plus-circle fa-fw"></i></span>';
|
||||||
|
$(td).html('<div><a href="#"><div style="float: left;">' + expand_details + ' ' + date + '</div></a></div>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<div style="float: left;"><i class="fa fa-fw"></i> ' + date + '</div>');
|
$(td).html('<div style="float: left;"><i class="fa fa-fw"></i> ' + date + '</div>');
|
||||||
}
|
}
|
||||||
|
@ -92,7 +95,7 @@ media_info_table_options = {
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=300&fallback=poster" data-height="80">T' + rowData['media_index'] + ' - ' + cellData + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=300&fallback=poster" data-height="80">T' + rowData['media_index'] + ' - ' + cellData + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?rating_key=' + rowData['rating_key'] + '"><div style="float: left; padding-left: 30px;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?rating_key=' + rowData['rating_key'] + '"><div style="float: left; padding-left: 30px;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="info?rating_key=' + rowData['rating_key'] + '">' + cellData + '</a>');
|
$(td).html(cellData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -291,6 +294,9 @@ function childTableOptionsMedia(rowData) {
|
||||||
case 'album':
|
case 'album':
|
||||||
section_type = 'track';
|
section_type = 'track';
|
||||||
break;
|
break;
|
||||||
|
case 'photo':
|
||||||
|
section_type = 'picture';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
media_info_table_options = media_info_table_options;
|
media_info_table_options = media_info_table_options;
|
||||||
|
@ -301,7 +307,7 @@ function childTableOptionsMedia(rowData) {
|
||||||
media_info_table_options.pageLength = 10;
|
media_info_table_options.pageLength = 10;
|
||||||
media_info_table_options.bStateSave = false;
|
media_info_table_options.bStateSave = false;
|
||||||
media_info_table_options.ajax = {
|
media_info_table_options.ajax = {
|
||||||
url: 'get_library_media_info2',
|
url: 'get_library_media_info',
|
||||||
type: 'post',
|
type: 'post',
|
||||||
data: function (d) {
|
data: function (d) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -342,7 +342,6 @@ DOCUMENTATION :: END
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
history_table = $('#history_table').DataTable(history_table_options);
|
history_table = $('#history_table').DataTable(history_table_options);
|
||||||
//history_table.column(2).visible(false);
|
|
||||||
|
|
||||||
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] });
|
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] });
|
||||||
$(colvis.button()).appendTo('#button-bar-history');
|
$(colvis.button()).appendTo('#button-bar-history');
|
||||||
|
@ -353,7 +352,7 @@ DOCUMENTATION :: END
|
||||||
function loadMediaInfoTable() {
|
function loadMediaInfoTable() {
|
||||||
// Build media info table
|
// Build media info table
|
||||||
media_info_table_options.ajax = {
|
media_info_table_options.ajax = {
|
||||||
url: 'get_library_media_info2',
|
url: 'get_library_media_info',
|
||||||
type: 'post',
|
type: 'post',
|
||||||
data: function ( d ) {
|
data: function ( d ) {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -89,6 +89,5 @@ DOCUMENTATION :: END
|
||||||
% endfor
|
% endfor
|
||||||
</ul>
|
</ul>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from server. Please check your <a href="settings">settings</a>.
|
<div class="text-muted">No stats to show for the selected period.</div><br>
|
||||||
</div><br>
|
|
||||||
% endif
|
% endif
|
|
@ -38,6 +38,5 @@ DOCUMENTATION :: END
|
||||||
</ul>
|
</ul>
|
||||||
% endfor
|
% endfor
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database.
|
<div class="text-muted">No stats to show.</div><br>
|
||||||
</div><br>
|
|
||||||
% endif
|
% endif
|
|
@ -39,6 +39,5 @@ DOCUMENTATION :: END
|
||||||
</script>
|
</script>
|
||||||
% endfor
|
% endfor
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database.
|
<div class="text-muted">No stats to show.</div><br>
|
||||||
</div><br>
|
|
||||||
% endif
|
% endif
|
|
@ -80,6 +80,5 @@ DOCUMENTATION :: END
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="text-muted">Unable to retrieve data from database.
|
<div class="text-muted">No stats to show.</div><br>
|
||||||
</div><br>
|
|
||||||
% endif
|
% endif
|
|
@ -364,13 +364,18 @@ def create_https_certificates(ssl_cert, ssl_key):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def cast_to_int(s):
|
||||||
|
try:
|
||||||
|
return int(s)
|
||||||
|
except ValueError:
|
||||||
|
return -1
|
||||||
|
|
||||||
def cast_to_float(s):
|
def cast_to_float(s):
|
||||||
try:
|
try:
|
||||||
return float(s)
|
return float(s)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
def convert_xml_to_json(xml):
|
def convert_xml_to_json(xml):
|
||||||
o = xmltodict.parse(xml)
|
o = xmltodict.parse(xml)
|
||||||
return json.dumps(o)
|
return json.dumps(o)
|
||||||
|
|
|
@ -120,104 +120,7 @@ class Libraries(object):
|
||||||
|
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
def get_datatables_media_info(self, section_id=None, kwargs=None):
|
def get_datatables_media_info(self, section_id=None, section_type=None, rating_key=None, kwargs=None):
|
||||||
data_tables = datatables.DataTables()
|
|
||||||
|
|
||||||
custom_where = ['library_sections.section_id', section_id]
|
|
||||||
|
|
||||||
columns = ['session_history.id',
|
|
||||||
'session_history.started AS last_watched',
|
|
||||||
'COUNT(DISTINCT session_history.reference_id) AS play_count',
|
|
||||||
'session_history_metadata.rating_key',
|
|
||||||
'session_history_metadata.parent_rating_key',
|
|
||||||
'session_history_metadata.grandparent_rating_key',
|
|
||||||
'session_history_metadata.full_title',
|
|
||||||
'session_history_metadata.year',
|
|
||||||
'session_history_metadata.media_index',
|
|
||||||
'session_history_metadata.parent_media_index',
|
|
||||||
'session_history_metadata.thumb',
|
|
||||||
'session_history_metadata.parent_thumb',
|
|
||||||
'session_history_metadata.grandparent_thumb',
|
|
||||||
'session_history_metadata.media_type',
|
|
||||||
'session_history_metadata.added_at',
|
|
||||||
'session_history_media_info.container',
|
|
||||||
'session_history_media_info.bitrate',
|
|
||||||
'session_history_media_info.video_codec',
|
|
||||||
'session_history_media_info.video_resolution',
|
|
||||||
'session_history_media_info.video_framerate',
|
|
||||||
'session_history_media_info.audio_codec',
|
|
||||||
'session_history_media_info.audio_channels',
|
|
||||||
'session_history_media_info.duration AS file_size'
|
|
||||||
]
|
|
||||||
|
|
||||||
try:
|
|
||||||
query = data_tables.ssp_query(table_name='session_history',
|
|
||||||
columns=columns,
|
|
||||||
custom_where=[custom_where],
|
|
||||||
group_by=['session_history_metadata.rating_key'],
|
|
||||||
join_types=['JOIN',
|
|
||||||
'JOIN',
|
|
||||||
'JOIN'],
|
|
||||||
join_tables=['library_sections',
|
|
||||||
'session_history_metadata',
|
|
||||||
'session_history_media_info'],
|
|
||||||
join_evals=[['session_history_metadata.section_id', 'library_sections.section_id'],
|
|
||||||
['session_history.id', 'session_history_metadata.id'],
|
|
||||||
['session_history.id', 'session_history_media_info.id']],
|
|
||||||
kwargs=kwargs)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_datatables_media_info: %s." % e)
|
|
||||||
return {'recordsFiltered': 0,
|
|
||||||
'recordsTotal': 0,
|
|
||||||
'draw': 0,
|
|
||||||
'data': 'null',
|
|
||||||
'error': 'Unable to execute database query.'}
|
|
||||||
|
|
||||||
results = query['result']
|
|
||||||
|
|
||||||
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_watched': item['last_watched'],
|
|
||||||
'added_at': item['added_at'],
|
|
||||||
'play_count': item['play_count'],
|
|
||||||
'media_type': item['media_type'],
|
|
||||||
'rating_key': item['rating_key'],
|
|
||||||
'parent_rating_key': item['parent_rating_key'],
|
|
||||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
|
||||||
'full_title': item['full_title'],
|
|
||||||
'year': item['year'],
|
|
||||||
'media_index': item['media_index'],
|
|
||||||
'parent_media_index': item['parent_media_index'],
|
|
||||||
'thumb': thumb,
|
|
||||||
'container': item['container'],
|
|
||||||
'bitrate': item['bitrate'],
|
|
||||||
'video_codec': item['video_codec'],
|
|
||||||
'video_resolution': item['video_resolution'],
|
|
||||||
'video_framerate': item['video_framerate'],
|
|
||||||
'audio_codec': item['audio_codec'],
|
|
||||||
'audio_channels': item['audio_channels'],
|
|
||||||
'file_size': item['file_size']
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.append(row)
|
|
||||||
|
|
||||||
dict = {'recordsFiltered': query['filteredCount'],
|
|
||||||
'recordsTotal': query['totalCount'],
|
|
||||||
'data': rows,
|
|
||||||
'draw': query['draw']
|
|
||||||
}
|
|
||||||
|
|
||||||
return dict
|
|
||||||
|
|
||||||
def get_datatables_media_info2(self, section_id=None, section_type=None, rating_key=None, kwargs=None):
|
|
||||||
from plexpy import pmsconnect
|
from plexpy import pmsconnect
|
||||||
import json, os
|
import json, os
|
||||||
|
|
||||||
|
@ -347,6 +250,9 @@ class Libraries(object):
|
||||||
}
|
}
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
|
if not rows:
|
||||||
|
return default_return
|
||||||
|
|
||||||
if rating_key:
|
if rating_key:
|
||||||
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s_%s.json' % (section_id, rating_key))
|
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info-%s_%s.json' % (section_id, rating_key))
|
||||||
with open(outFilePath, 'w') as outFile:
|
with open(outFilePath, 'w') as outFile:
|
||||||
|
@ -367,11 +273,10 @@ class Libraries(object):
|
||||||
search_value = json_data['search']['value'].lower()
|
search_value = json_data['search']['value'].lower()
|
||||||
if search_value:
|
if search_value:
|
||||||
searchable_columns = [d['data'] for d in json_data['columns'] if d['searchable']]
|
searchable_columns = [d['data'] for d in json_data['columns'] if d['searchable']]
|
||||||
for row in rows:
|
for k,v in [row.iteritems() for row in rows]:
|
||||||
for k,v in row.iteritems():
|
if k in searchable_columns and search_value in v.lower():
|
||||||
if k in searchable_columns and search_value in v.lower():
|
results.append(row)
|
||||||
results.append(row)
|
break
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
results = rows
|
results = rows
|
||||||
|
|
||||||
|
@ -384,9 +289,9 @@ class Libraries(object):
|
||||||
sort_key = json_data['columns'][int(order['column'])]['data']
|
sort_key = json_data['columns'][int(order['column'])]['data']
|
||||||
reverse = True if order['dir'] == 'desc' else False
|
reverse = True if order['dir'] == 'desc' else False
|
||||||
if rating_key and sort_key == 'title':
|
if rating_key and sort_key == 'title':
|
||||||
results = sorted(results, key=lambda k: int(k['media_index']), reverse=reverse)
|
results = sorted(results, key=lambda k: helpers.cast_to_int(k['media_index']), reverse=reverse)
|
||||||
elif sort_key == 'file_size' or sort_key == 'bitrate':
|
elif sort_key == 'file_size' or sort_key == 'bitrate':
|
||||||
results = sorted(results, key=lambda k: int(k[sort_key]), reverse=reverse)
|
results = sorted(results, key=lambda k: helpers.cast_to_int(k[sort_key]), reverse=reverse)
|
||||||
else:
|
else:
|
||||||
results = sorted(results, key=lambda k: k[sort_key], reverse=reverse)
|
results = sorted(results, key=lambda k: k[sort_key], reverse=reverse)
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ def refresh_libraries():
|
||||||
library_keys.append(section['section_id'])
|
library_keys.append(section['section_id'])
|
||||||
|
|
||||||
|
|
||||||
if plexpy.CONFIG.HOME_LIBRARY_CARDS == ['first_run']:
|
if plexpy.CONFIG.HOME_LIBRARY_CARDS == ['first_run_wizard']:
|
||||||
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_keys)
|
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_keys)
|
||||||
plexpy.CONFIG.write()
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
|
@ -1619,17 +1619,16 @@ class PmsConnect(object):
|
||||||
|
|
||||||
# Get show/season info from xml_head
|
# Get show/season info from xml_head
|
||||||
|
|
||||||
|
item_main = []
|
||||||
if a.getElementsByTagName('Directory'):
|
if a.getElementsByTagName('Directory'):
|
||||||
item_main = a.getElementsByTagName('Directory')
|
dir_main = a.getElementsByTagName('Directory')
|
||||||
item_main = [d for d in item_main if helpers.get_xml_attr(d, 'ratingKey')]
|
item_main += [d for d in dir_main if helpers.get_xml_attr(d, 'ratingKey')]
|
||||||
elif a.getElementsByTagName('Video'):
|
if a.getElementsByTagName('Video'):
|
||||||
item_main = a.getElementsByTagName('Video')
|
item_main += a.getElementsByTagName('Video')
|
||||||
elif a.getElementsByTagName('Track'):
|
if a.getElementsByTagName('Track'):
|
||||||
item_main = a.getElementsByTagName('Track')
|
item_main += a.getElementsByTagName('Track')
|
||||||
elif a.getElementsByTagName('Photo'):
|
if a.getElementsByTagName('Photo'):
|
||||||
item_main = a.getElementsByTagName('Photo')
|
item_main += a.getElementsByTagName('Photo')
|
||||||
else:
|
|
||||||
item_main = []
|
|
||||||
|
|
||||||
for item in item_main:
|
for item in item_main:
|
||||||
item_info = {'section_id': helpers.get_xml_attr(a, 'librarySectionID'),
|
item_info = {'section_id': helpers.get_xml_attr(a, 'librarySectionID'),
|
||||||
|
|
|
@ -97,7 +97,7 @@ class Users(object):
|
||||||
|
|
||||||
row = {'user_id': item['user_id'],
|
row = {'user_id': item['user_id'],
|
||||||
'username': item['username'],
|
'username': item['username'],
|
||||||
'friendly_name': item['friendly_name'],
|
'friendly_name': friendly_name,
|
||||||
'user_thumb': user_thumb,
|
'user_thumb': user_thumb,
|
||||||
'plays': item['plays'],
|
'plays': item['plays'],
|
||||||
'last_seen': item['last_seen'],
|
'last_seen': item['last_seen'],
|
||||||
|
|
|
@ -176,7 +176,7 @@ class WebInterface(object):
|
||||||
try:
|
try:
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_current_activity()
|
result = pms_connect.get_current_activity()
|
||||||
except IOError, e:
|
except:
|
||||||
return serve_template(templatename="current_activity_header.html", data=None)
|
return serve_template(templatename="current_activity_header.html", data=None)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
@ -362,14 +362,14 @@ class WebInterface(object):
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def get_library_media_info2(self, section_id=None, section_type=None, rating_key=None, **kwargs):
|
def get_library_media_info(self, section_id=None, section_type=None, rating_key=None, **kwargs):
|
||||||
|
|
||||||
library_data = libraries.Libraries()
|
library_data = libraries.Libraries()
|
||||||
result = library_data.get_datatables_media_info2(section_id=section_id,
|
result = library_data.get_datatables_media_info(section_id=section_id,
|
||||||
section_type=section_type,
|
section_type=section_type,
|
||||||
rating_key=rating_key,
|
rating_key=rating_key,
|
||||||
kwargs=kwargs)
|
kwargs=kwargs)
|
||||||
|
|
||||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
@ -1147,16 +1147,24 @@ class WebInterface(object):
|
||||||
refresh_users = True
|
refresh_users = True
|
||||||
|
|
||||||
# Remove config with 'hscard-' prefix and change home_stats_cards to list
|
# Remove config with 'hscard-' prefix and change home_stats_cards to list
|
||||||
for k in kwargs.keys():
|
if 'home_stats_cards' in kwargs:
|
||||||
if k.startswith('hscard-'):
|
for k in kwargs.keys():
|
||||||
del kwargs[k]
|
if k.startswith('hscard-'):
|
||||||
kwargs['home_stats_cards'] = kwargs['home_stats_cards'].split(',')
|
del kwargs[k]
|
||||||
|
kwargs['home_stats_cards'] = kwargs['home_stats_cards'].split(',')
|
||||||
|
|
||||||
|
if kwargs['home_stats_cards'] == ['first_run_wizard']:
|
||||||
|
kwargs['home_stats_cards'] = plexpy.CONFIG.HOME_STATS_CARDS
|
||||||
|
|
||||||
# Remove config with 'hlcard-' prefix and change home_library_cards to list
|
# Remove config with 'hlcard-' prefix and change home_library_cards to list
|
||||||
for k in kwargs.keys():
|
if 'home_library_cards' in kwargs:
|
||||||
if k.startswith('hlcard-'):
|
for k in kwargs.keys():
|
||||||
del kwargs[k]
|
if k.startswith('hlcard-'):
|
||||||
kwargs['home_library_cards'] = kwargs['home_library_cards'].split(',')
|
del kwargs[k]
|
||||||
|
kwargs['home_library_cards'] = kwargs['home_library_cards'].split(',')
|
||||||
|
|
||||||
|
if kwargs['home_library_cards'] == ['first_run_wizard']:
|
||||||
|
refresh_libraries = True
|
||||||
|
|
||||||
plexpy.CONFIG.process_kwargs(kwargs)
|
plexpy.CONFIG.process_kwargs(kwargs)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue