mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 05:31:15 -07:00
Implement friendly names across entire project scope.
This commit is contained in:
parent
e7b305a1d5
commit
6f7194593b
8 changed files with 121 additions and 66 deletions
|
@ -30,7 +30,7 @@ from plexpy import helpers
|
|||
<tr>
|
||||
<th class="never" align='left' id="id">ID</th>
|
||||
<th class="all" align='left' id="time">Time</th>
|
||||
<th class="all" align='left' id="user">User</th>
|
||||
<th class="all" align='left' id="friendly_name">User</th>
|
||||
<th class="desktop" align='left' id="platform">Platform</th>
|
||||
<th class="desktop" align='left' id="ip_address">IP Address</th>
|
||||
<th class="min-tablet" align='left' id="title">Title</th>
|
||||
|
@ -41,6 +41,7 @@ from plexpy import helpers
|
|||
<th class="desktop" align='left' id="percent_complete">Completed</th>
|
||||
<th class="never" align='left' id="rating_key">RatingKey</th>
|
||||
<th class="never" align='left' id="xml"></th>
|
||||
<th class="never" align='left' id="user"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -189,7 +189,7 @@ from plexpy import helpers
|
|||
<tr>
|
||||
<th class="never" align='left' id="id">ID</th>
|
||||
<th class="all" align='left' id="time">Time</th>
|
||||
<th class="all" align='left' id="user">User</th>
|
||||
<th class="all" align='left' id="friendly_name">User</th>
|
||||
<th class="desktop" align='left' id="platform">Platform</th>
|
||||
<th class="desktop" align='left' id="ip_address">IP Address</th>
|
||||
<th class="min-tablet" align='left' id="title">Title</th>
|
||||
|
@ -200,6 +200,7 @@ from plexpy import helpers
|
|||
<th class="desktop" align='left' id="percent_complete">Completed</th>
|
||||
<th class="never" align='left' id="rating_key">RatingKey</th>
|
||||
<th class="never" align='left' id="xml"></th>
|
||||
<th class="never" align='left' id="user"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -53,10 +53,10 @@ history_table_options = {
|
|||
},
|
||||
{
|
||||
"targets": [2],
|
||||
"data":"user",
|
||||
"data":"friendly_name",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
if (cellData !== '') {
|
||||
$(td).html('<a href="user?user=' + cellData + '">' + cellData + '</a>');
|
||||
$(td).html('<a href="user?user=' + rowData['user'] + '">' + cellData + '</a>');
|
||||
} else {
|
||||
$(td).html(cellData);
|
||||
}
|
||||
|
@ -162,7 +162,14 @@ history_table_options = {
|
|||
"data":"xml",
|
||||
"searchable":false,
|
||||
"visible":false
|
||||
},
|
||||
{
|
||||
"targets": [13],
|
||||
"data":"user",
|
||||
"searchable":false,
|
||||
"visible":false
|
||||
}
|
||||
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
|
@ -187,7 +194,7 @@ $('#history_table').on('click', 'td.modal-control', function () {
|
|||
function showStreamDetails() {
|
||||
$.ajax({
|
||||
url: 'get_stream_data',
|
||||
data: {row_id: rowData['id'], user: rowData['user']},
|
||||
data: {row_id: rowData['id'], user: rowData['friendly_name']},
|
||||
cache: false,
|
||||
async: true,
|
||||
complete: function(xhr, status) {
|
||||
|
|
|
@ -18,12 +18,8 @@ users_list_table_options = {
|
|||
"ajax": {
|
||||
"url": "get_user_list"
|
||||
},
|
||||
"bLengthChange": true,
|
||||
"bInfo": true,
|
||||
"bAutoWidth": true,
|
||||
"aaSorting": [[ 0, "asc" ]],
|
||||
"bStateSave": true,
|
||||
"bSortClasses": true,
|
||||
"autoWidth": true,
|
||||
"stateSave": true,
|
||||
"sPaginationType": "bootstrap",
|
||||
"columnDefs": [
|
||||
{
|
||||
|
@ -42,10 +38,10 @@ users_list_table_options = {
|
|||
},
|
||||
{
|
||||
"targets": [1],
|
||||
"data": "user",
|
||||
"data": "friendly_name",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
if (cellData !== '') {
|
||||
$(td).html('<a href="user?user=' + cellData + '">' + cellData + '</a>');
|
||||
$(td).html('<a href="user?user=' + rowData['user'] + '">' + cellData + '</a>');
|
||||
} else {
|
||||
$(td).html(cellData);
|
||||
}
|
||||
|
@ -66,7 +62,14 @@ users_list_table_options = {
|
|||
{
|
||||
"targets": [4],
|
||||
"data": "plays"
|
||||
},
|
||||
{
|
||||
"targets": [5],
|
||||
"data": "user",
|
||||
"searchable": false,
|
||||
"visible": false
|
||||
}
|
||||
|
||||
],
|
||||
"drawCallback": function (settings) {
|
||||
// Jump to top of page
|
||||
|
|
|
@ -177,7 +177,7 @@ from plexpy import helpers
|
|||
<tr>
|
||||
<th class="never" align='left' id="id">ID</th>
|
||||
<th class="all" align='left' id="time">Time</th>
|
||||
<th class="never" align='left' id="user">User</th>
|
||||
<th class="never" align='left' id="friendly_name">User</th>
|
||||
<th class="min-tablet" align='left' id="platform">Platform</th>
|
||||
<th class="desktop" align='left' id="ip_address">IP Address</th>
|
||||
<th class="min-tablet" align='left' id="title">Title</th>
|
||||
|
@ -188,6 +188,7 @@ from plexpy import helpers
|
|||
<th class="desktop" align='left' id="percent_complete">Completed</th>
|
||||
<th class="never" align='left' id="rating_key">RatingKey</th>
|
||||
<th class="never" align='left' id="xml"></th>
|
||||
<th class="never" align='left' id="user"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -28,10 +28,11 @@ from plexpy import helpers
|
|||
<thead>
|
||||
<tr>
|
||||
<th class="all" align="right" id="avatar"></th>
|
||||
<th class="all" align="left" id="username">User</th>
|
||||
<th class="all" align="left" id="friendly_name">User</th>
|
||||
<th class="min-tablet" align="left" id="last_seen">Last Seen</th>
|
||||
<th class="min-tablet" align="left" id="last_known_ip">Last Known IP</th>
|
||||
<th class="min-tablet" align="left" id="total_plays">Total Plays</th>
|
||||
<th class="never" align="left" id="user"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -39,6 +39,9 @@ class DataTables(object):
|
|||
search_regex='',
|
||||
custom_where='',
|
||||
group_by='',
|
||||
join_type=None,
|
||||
join_table=None,
|
||||
join_evals=None,
|
||||
kwargs=None):
|
||||
|
||||
parameters = self.process_kwargs(kwargs)
|
||||
|
@ -50,7 +53,14 @@ class DataTables(object):
|
|||
|
||||
column_data = self.extract_columns(columns)
|
||||
where = self.construct_where(column_data, search_value, grouping, parameters)
|
||||
order = self.construct_order(column_data, order_column, order_dir, parameters)
|
||||
order = self.construct_order(column_data, order_column, order_dir, parameters, table_name, grouping)
|
||||
join = ''
|
||||
|
||||
if join_type:
|
||||
if join_type.upper() == 'LEFT OUTER JOIN':
|
||||
join = 'LEFT OUTER JOIN %s ON %s = %s' % (join_table, join_evals[0], join_evals[1])
|
||||
else:
|
||||
join = ''
|
||||
|
||||
# TODO: custom_where is ugly and causes issues with reported total results
|
||||
if custom_where != '':
|
||||
|
@ -58,21 +68,21 @@ class DataTables(object):
|
|||
|
||||
if grouping:
|
||||
if custom_where == '':
|
||||
query = 'SELECT * FROM (SELECT %s FROM %s GROUP BY %s) %s %s' \
|
||||
% (column_data['column_string'], table_name, group_by,
|
||||
query = 'SELECT * FROM (SELECT %s FROM %s %s GROUP BY %s) %s %s' \
|
||||
% (column_data['column_string'], table_name, join, group_by,
|
||||
where, order)
|
||||
else:
|
||||
query = 'SELECT * FROM (SELECT * FROM (SELECT %s FROM %s GROUP BY %s) %s %s) %s' \
|
||||
% (column_data['column_string'], table_name, group_by,
|
||||
query = 'SELECT * FROM (SELECT * FROM (SELECT %s FROM %s %s GROUP BY %s) %s %s) %s' \
|
||||
% (column_data['column_string'], table_name, join, group_by,
|
||||
where, order, custom_where)
|
||||
else:
|
||||
if custom_where == '':
|
||||
query = 'SELECT %s FROM %s %s %s' \
|
||||
% (column_data['column_string'], table_name, where,
|
||||
query = 'SELECT %s FROM %s %s %s %s' \
|
||||
% (column_data['column_string'], table_name, join, where,
|
||||
order)
|
||||
else:
|
||||
query = 'SELECT * FROM (SELECT %s FROM %s %s %s) %s' \
|
||||
% (column_data['column_string'], table_name, where,
|
||||
query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s) %s' \
|
||||
% (column_data['column_string'], table_name, join, where,
|
||||
order, custom_where)
|
||||
|
||||
# logger.debug(u"Query string: %s" % query)
|
||||
|
@ -91,16 +101,23 @@ class DataTables(object):
|
|||
return output
|
||||
|
||||
@staticmethod
|
||||
def construct_order(column_data, order_column, order_dir, parameters=None):
|
||||
def construct_order(column_data, order_column, order_dir, parameters=None, table_name=None, grouped=False):
|
||||
order = ''
|
||||
if grouped:
|
||||
sort_col = column_data['column_named'][order_column]
|
||||
else:
|
||||
sort_col = column_data['column_order'][order_column]
|
||||
if parameters:
|
||||
for parameter in parameters:
|
||||
if parameter['data'] != '':
|
||||
if int(order_column) == parameter['index']:
|
||||
if parameter['data'] in column_data['column_named'] and parameter['orderable'] == 'true':
|
||||
order = 'ORDER BY %s COLLATE NOCASE %s' % (parameter['data'], order_dir)
|
||||
if table_name and table_name != '':
|
||||
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
|
||||
else:
|
||||
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
|
||||
else:
|
||||
order = 'ORDER BY %s COLLATE NOCASE %s' % (column_data['column_named'][order_column], order_dir)
|
||||
order = 'ORDER BY %s COLLATE NOCASE %s' % (sort_col, order_dir)
|
||||
|
||||
return order
|
||||
|
||||
|
@ -112,7 +129,7 @@ class DataTables(object):
|
|||
for column in column_data['column_named']:
|
||||
search_skip = False
|
||||
for parameter in parameters:
|
||||
if column in parameter['data']:
|
||||
if column.rpartition('.')[-1] in parameter['data']:
|
||||
if parameter['searchable'] == 'true':
|
||||
where += column + ' LIKE "%' + search_value + '%" OR '
|
||||
search_skip = True
|
||||
|
@ -139,6 +156,7 @@ class DataTables(object):
|
|||
columns_string = ''
|
||||
columns_literal = []
|
||||
columns_named = []
|
||||
columns_order = []
|
||||
|
||||
for column in columns:
|
||||
columns_string += column
|
||||
|
@ -146,23 +164,25 @@ class DataTables(object):
|
|||
# TODO: make this case insensitive
|
||||
if ' as ' in column:
|
||||
columns_literal.append(column.rpartition(' as ')[0])
|
||||
columns_named.append(column.rpartition(' as ')[-1])
|
||||
columns_named.append(column.rpartition(' as ')[-1].rpartition('.')[-1])
|
||||
columns_order.append(column.rpartition(' as ')[-1])
|
||||
else:
|
||||
columns_literal.append(column)
|
||||
columns_named.append(column)
|
||||
columns_named.append(column.rpartition('.')[-1])
|
||||
columns_order.append(column)
|
||||
|
||||
columns_string = columns_string[:-2]
|
||||
|
||||
column_data = {'column_string': columns_string,
|
||||
'column_literal': columns_literal,
|
||||
'column_named': columns_named
|
||||
'column_named': columns_named,
|
||||
'column_order': columns_order
|
||||
}
|
||||
|
||||
return column_data
|
||||
|
||||
# TODO: Fix this method. Should not break if kwarg list is not sorted.
|
||||
@staticmethod
|
||||
def process_kwargs(kwargs):
|
||||
def process_kwargs(self, kwargs):
|
||||
|
||||
column_parameters = []
|
||||
|
||||
|
|
|
@ -64,12 +64,16 @@ class PlexWatch(object):
|
|||
if 'search[regex]' in kwargs:
|
||||
search_regex = kwargs.get('search[regex]', "")
|
||||
|
||||
columns = ['user',
|
||||
'time',
|
||||
'ip_address',
|
||||
'COUNT(title) as plays']
|
||||
t = self.get_history_table_name()
|
||||
|
||||
columns = [t + '.id',
|
||||
'(case when plexpy_users.friendly_name is null then ' + t + '.user else plexpy_users.friendly_name end) as friendly_name',
|
||||
t + '.time',
|
||||
t + '.ip_address',
|
||||
'COUNT(' + t + '.title) as plays',
|
||||
t + '.user']
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name=self.get_history_table_name(),
|
||||
query = data_tables.ssp_query(table_name=t,
|
||||
columns=columns,
|
||||
start=start,
|
||||
length=length,
|
||||
|
@ -78,7 +82,10 @@ class PlexWatch(object):
|
|||
search_value=search_value,
|
||||
search_regex=search_regex,
|
||||
custom_where='',
|
||||
group_by='user',
|
||||
group_by=(t + '.user'),
|
||||
join_type='LEFT OUTER JOIN',
|
||||
join_table='plexpy_users',
|
||||
join_evals=[t + '.user', 'plexpy_users.username'],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to open PlexWatch database.")
|
||||
|
@ -94,9 +101,10 @@ class PlexWatch(object):
|
|||
|
||||
row = {"plays": item['plays'],
|
||||
"time": item['time'],
|
||||
"user": item["user"],
|
||||
"friendly_name": item["friendly_name"],
|
||||
"ip_address": item["ip_address"],
|
||||
"thumb": thumb['user_thumb']
|
||||
"thumb": thumb['user_thumb'],
|
||||
"user": item["user"]
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
@ -132,12 +140,14 @@ class PlexWatch(object):
|
|||
if 'search[regex]' in kwargs:
|
||||
search_regex = kwargs.get('search[regex]', "")
|
||||
|
||||
columns = ['time as last_seen',
|
||||
'ip_address',
|
||||
'COUNT(ip_address) as play_count',
|
||||
'platform',
|
||||
'user',
|
||||
'orig_title as last_watched'
|
||||
t = self.get_history_table_name()
|
||||
|
||||
columns = [t + '.time as last_seen',
|
||||
t + '.user',
|
||||
t + '.ip_address',
|
||||
'COUNT(' + t + '.ip_address) as play_count',
|
||||
t + '.platform',
|
||||
t + '.title as last_watched'
|
||||
]
|
||||
|
||||
try:
|
||||
|
@ -150,7 +160,10 @@ class PlexWatch(object):
|
|||
search_value=search_value,
|
||||
search_regex=search_regex,
|
||||
custom_where=custom_where,
|
||||
group_by='ip_address',
|
||||
group_by=(t + '.ip_address'),
|
||||
join_type=None,
|
||||
join_table=None,
|
||||
join_evals=None,
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to open PlexWatch database.")
|
||||
|
@ -190,6 +203,8 @@ class PlexWatch(object):
|
|||
order_column = 1
|
||||
order_dir = "desc"
|
||||
|
||||
t = self.get_history_table_name()
|
||||
|
||||
if 'order[0][dir]' in kwargs:
|
||||
order_dir = kwargs.get('order[0][dir]', "desc")
|
||||
|
||||
|
@ -202,24 +217,25 @@ class PlexWatch(object):
|
|||
if 'search[regex]' in kwargs:
|
||||
search_regex = kwargs.get('search[regex]', "")
|
||||
|
||||
columns = ['id',
|
||||
'time as date',
|
||||
'user',
|
||||
'platform',
|
||||
'ip_address',
|
||||
'title',
|
||||
'time as started',
|
||||
'paused_counter',
|
||||
'stopped',
|
||||
'ratingKey as rating_key',
|
||||
'xml',
|
||||
'round((julianday(datetime(stopped, "unixepoch", "localtime")) - \
|
||||
julianday(datetime(time, "unixepoch", "localtime"))) * 86400) - \
|
||||
(case when paused_counter is null then 0 else paused_counter end) as duration',
|
||||
'grandparentRatingKey as grandparent_rating_key'
|
||||
columns = [t + '.id',
|
||||
t + '.time as date',
|
||||
'(case when plexpy_users.friendly_name is null then ' + t + '.user else plexpy_users.friendly_name end) as friendly_name',
|
||||
t + '.platform',
|
||||
t + '.ip_address',
|
||||
t + '.title',
|
||||
t + '.time as started',
|
||||
t + '.paused_counter',
|
||||
t + '.stopped',
|
||||
'round((julianday(datetime(' + t + '.stopped, "unixepoch", "localtime")) - \
|
||||
julianday(datetime(' + t + '.time, "unixepoch", "localtime"))) * 86400) - \
|
||||
(case when ' + t + '.paused_counter is null then 0 else ' + t + '.paused_counter end) as duration',
|
||||
t + '.ratingKey as rating_key',
|
||||
t + '.xml',
|
||||
t + '.user',
|
||||
t + '.grandparentRatingKey as grandparent_rating_key'
|
||||
]
|
||||
try:
|
||||
query = data_tables.ssp_query(table_name=self.get_history_table_name(),
|
||||
query = data_tables.ssp_query(table_name=t,
|
||||
columns=columns,
|
||||
start=start,
|
||||
length=length,
|
||||
|
@ -229,6 +245,9 @@ class PlexWatch(object):
|
|||
search_regex=search_regex,
|
||||
custom_where=custom_where,
|
||||
group_by='',
|
||||
join_type='LEFT OUTER JOIN',
|
||||
join_table='plexpy_users',
|
||||
join_evals=[t + '.user', 'plexpy_users.username'],
|
||||
kwargs=kwargs)
|
||||
except:
|
||||
logger.warn("Unable to open PlexWatch database.")
|
||||
|
@ -243,7 +262,7 @@ class PlexWatch(object):
|
|||
for item in history:
|
||||
row = {"id": item['id'],
|
||||
"date": item['date'],
|
||||
"user": item["user"],
|
||||
"friendly_name": item['friendly_name'],
|
||||
"platform": item["platform"],
|
||||
"ip_address": item["ip_address"],
|
||||
"title": item["title"],
|
||||
|
@ -253,7 +272,9 @@ class PlexWatch(object):
|
|||
"rating_key": item["rating_key"],
|
||||
"duration": item["duration"],
|
||||
"percent_complete": 0,
|
||||
"xml": ""}
|
||||
"xml": "",
|
||||
"user": item["user"]
|
||||
}
|
||||
|
||||
if item['paused_counter'] > 0:
|
||||
row['paused_counter'] = item['paused_counter']
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue