Add option to change library background art

This commit is contained in:
JonnyWong16 2020-03-03 12:24:05 -08:00
parent cbab7c4cbf
commit ecee50a5e4
10 changed files with 143 additions and 82 deletions

1
API.md
View file

@ -327,6 +327,7 @@ Required parameters:
Optional parameters:
custom_thumb (str): The URL for the custom library thumbnail
custom_art (str): The URL for the custom library background art
keep_history (int): 0 or 1
Returns:

View file

@ -40,13 +40,22 @@ DOCUMENTATION :: END
<div class="modal-body" id="modal-text">
<fieldset>
<div class="form-group">
<label for="profile_url">Library Picture URL</label>
<label for="profile_url">Library Thumbnail URL</label>
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" id="custom_thumb_url" name="custom_thumb_url" value="${data['library_thumb']}">
</div>
</div>
<p class="help-block">Change the library's picture in Tautulli. To reset to default, leave this field empty and save.</p>
<p class="help-block">Change the library's thumbnail in Tautulli. To reset to default, leave this field empty and save.</p>
</div>
<div class="form-group">
<label for="profile_url">Library Background Art URL</label>
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" id="custom_art_url" name="custom_art_url" value="${data['library_art']}">
</div>
</div>
<p class="help-block">Change the library's background art in Tautulli. To reset to default, leave this field empty and save.</p>
</div>
<div class="checkbox">
<label>
@ -80,6 +89,7 @@ DOCUMENTATION :: END
// Save library options
$("#save_library").on('click', function () {
var custom_thumb = $("#custom_thumb_url").val();
var custom_art = $("#custom_art_url").val();
var keep_history = 0;
if ($("#keep_history").is(":checked")) {
keep_history = 1;
@ -90,6 +100,7 @@ DOCUMENTATION :: END
data: {
section_id: '${data["section_id"]}',
custom_thumb: custom_thumb,
custom_art: custom_art,
keep_history: keep_history
},
cache: false,

View file

@ -183,76 +183,6 @@ DOCUMENTATION :: END
</div>
% endif
% endfor
<script>
$('.dashboard-stats-instance .dashboard-stats-info-scroller').scrollbar();
function changeImages(elem) {
var stat_id = $(elem).data('stat_id');
var art = $(elem).data('art');
var thumb = $(elem).data('thumb');
var user_id = $(elem).data('user_id');
var user_thumb = $(elem).data('user_thumb');
var rating_key = $(elem).data('rating_key');
var guid = $(elem).data('guid');
var live = $(elem).data('live');
var [height, fallback_poster, fallback_art] = [450, 'poster', 'art'];
if ($.inArray(stat_id, ['top_music', 'popular_music']) > -1) {
[height, fallback_poster, fallback_art] = [300, 'cover', 'art'];
} else if (live) {
[height, fallback_poster, fallback_art] = [450, 'poster-live', 'art-live'];
}
var href = '#';
if (stat_id === 'most_concurrent') {
return
} else if (stat_id === 'top_users') {
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + (user_thumb || 'images/gravatar-default.png') + ')');
if (user_id) {
href = page('user', user_id);
}
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('friendly_name'));
} else if (stat_id === 'top_platforms') {
$('#stats-thumb-' + stat_id).removeClass(function (index, className) {
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
}).addClass('platform-' + $(elem).data('platform'));
$('#stats-background-' + stat_id).removeClass(function (index, className) {
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
}).addClass('platform-' + $(elem).data('platform') + '-rgba');
} else {
if (rating_key) {
if (live) {
href = page('info', rating_key, guid, true, live);
} else {
href = page('info', rating_key);
}
}
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('title'));
$('#stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art, rating_key, 500, 280, 40, '282828', 3, fallback_art) + ')');
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', thumb, rating_key, 300, height, null, null, null, fallback_poster) + ')');
$('#stats-thumb-' + stat_id + '-bg').css('background-image', 'url(' + page('pms_image_proxy', thumb, rating_key, 300, height, 60, '282828', 3, fallback_poster) + ')');
}
}
$('.dashboard-stats-info-item').mouseenter(function () {
changeImages(this);
if ($(this).data('stat_id') === 'last_watched') {
var friendly_name = $(this).data('friendly_name');
var last_watch = moment($(this).data('last_watch'), 'X').format(date_format);
$('#last-watched-header-info').html(friendly_name);
} else if ($(this).data('stat_id') === 'most_concurrent') {
var started = moment($(this).data('started'), 'X').format(date_format + ' ' + time_format);
$('#most-concurrent-header-info').html(started);
}
});
$('.dashboard-stats-instance').mouseleave(function () {
changeImages($(this).find('.dashboard-stats-info-item').first());
if ($(this).data('stat_id') === 'last_watched') {
$('#last-watched-header-info').text($(this).find('.dashboard-stats-info-item').first().data('friendly_name'));
} else if ($(this).data('stat_id') === 'most_concurrent') {
$('#most-concurrent-header-info').text('streams');
}
});
</script>
% else:
<div class="text-muted">No stats to show for the selected period.</div><br>
% endif

View file

@ -726,6 +726,88 @@
% endif
</script>
% endif
% if 'watch_stats' in config['home_sections'] or 'library_stats' in config['home_sections']:
<script>
function statsCardCallback() {
$('.dashboard-stats-instance .dashboard-stats-info-scroller').scrollbar();
function changeImages(elem) {
var stat_id = $(elem).data('stat_id');
var art = $(elem).data('art');
var thumb = $(elem).data('thumb');
var user_id = $(elem).data('user_id');
var user_thumb = $(elem).data('user_thumb');
var rating_key = $(elem).data('rating_key');
var guid = $(elem).data('guid');
var live = $(elem).data('live');
var [height, fallback_poster, fallback_art] = [450, 'poster', 'art'];
if ($.inArray(stat_id, ['top_music', 'popular_music']) > -1) {
[height, fallback_poster, fallback_art] = [300, 'cover', 'art'];
} else if (live) {
[height, fallback_poster, fallback_art] = [450, 'poster-live', 'art-live'];
}
var href = '#';
if (stat_id === 'most_concurrent') {
return
} else if (stat_id === 'top_users') {
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + (user_thumb || 'images/gravatar-default.png') + ')');
if (user_id) {
href = page('user', user_id);
}
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('friendly_name'));
} else if (stat_id === 'top_platforms') {
$('#stats-thumb-' + stat_id).removeClass(function (index, className) {
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
}).addClass('platform-' + $(elem).data('platform'));
$('#stats-background-' + stat_id).removeClass(function (index, className) {
return (className.match (/(^|\s)platform-\S+/g) || []).join(' ');
}).addClass('platform-' + $(elem).data('platform') + '-rgba');
} else {
if (rating_key) {
if (live) {
href = page('info', rating_key, guid, true, live);
} else {
href = page('info', rating_key);
}
}
$('#stats-thumb-url-' + stat_id).attr('href', href).prop('title', $(elem).data('title'));
$('#stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art, rating_key, 500, 280, 40, '282828', 3, fallback_art) + ')');
$('#stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', thumb, rating_key, 300, height, null, null, null, fallback_poster) + ')');
$('#stats-thumb-' + stat_id + '-bg').css('background-image', 'url(' + page('pms_image_proxy', thumb, rating_key, 300, height, 60, '282828', 3, fallback_poster) + ')');
$('#library-stats-background-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', art, rating_key, 500, 280, 40, '282828', 3, fallback_art) + ')');
if (thumb.startsWith('http')) {
$('#library-stats-thumb-' + stat_id).css('background-image', 'url(' + page('pms_image_proxy', thumb, rating_key, 300, 300, null, null, null, 'cover') + ')')
.removeClass('svg-icon library-' + stat_id);
} else {
$('#library-stats-thumb-' + stat_id).css('background-image', '')
.addClass('svg-icon library-' + stat_id);
}
}
}
$('.dashboard-stats-info-item').mouseenter(function () {
changeImages(this);
if ($(this).data('stat_id') === 'last_watched') {
var friendly_name = $(this).data('friendly_name');
var last_watch = moment($(this).data('last_watch'), 'X').format(date_format);
$('#last-watched-header-info').html(friendly_name);
} else if ($(this).data('stat_id') === 'most_concurrent') {
var started = moment($(this).data('started'), 'X').format(date_format + ' ' + time_format);
$('#most-concurrent-header-info').html(started);
}
});
$('.dashboard-stats-instance').mouseleave(function () {
changeImages($(this).find('.dashboard-stats-info-item').first());
if ($(this).data('stat_id') === 'last_watched') {
$('#last-watched-header-info').text($(this).find('.dashboard-stats-info-item').first().data('friendly_name'));
} else if ($(this).data('stat_id') === 'most_concurrent') {
$('#most-concurrent-header-info').text('streams');
}
});
}
</script>
% endif
% if 'watch_stats' in config['home_sections']:
<script>
function getHomeStats(time_range, stats_type) {
@ -744,6 +826,7 @@
$("#home-stats").html(xhr.responseText);
$('#ajaxMsg').fadeOut();
lockScroll('#home-stats .dashboard-stats-info-scroller');
statsCardCallback();
}
});
}
@ -783,6 +866,7 @@
data: { },
complete: function (xhr, status) {
$("#library-stats").html(xhr.responseText);
statsCardCallback();
}
});
}

View file

@ -61,8 +61,8 @@ DOCUMENTATION :: END
<div class="col-md-12">
<div class="table-card-back">
<div class="user-info-wrapper">
% if data['library_thumb'][:4] == 'http':
<div class="library-info-poster-face" style="background-image: url(${data['library_thumb']});"></div>
% if data['library_thumb'].startswith('http'):
<div class="library-info-poster-face" style="background-image: url(${page('pms_image_proxy', data['library_thumb'], None, 80, 80)});"></div>
% else:
<div class="library-info-poster-face svg-icon library-${data['section_type']}"></div>
% endif

View file

@ -35,10 +35,17 @@ DOCUMENTATION :: END
%>
% for section_type in types:
% if section_type in data:
<%
row0 = data[section_type][0]
%>
<div class="dashboard-stats-instance" id="library-stats-instance-${section_type}" data-section_type="${section_type}">
<div class="dashboard-stats-container">
<div id="library-stats-background-${section_type}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', '/:/resources/' + section_type + '-fanart.jpg', None, 500, 280, 40, '282828', 3, fallback='art')});">
<div id="library-stats-background-${section_type}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'], None, 500, 280, 40, '282828', 3, fallback='art')});">
% if row0['thumb'].startswith('http'):
<div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat hidden-xs" style="background-image: url(${page('pms_image_proxy', row0['thumb'], None, 80, 80)});"></div>
% else:
<div id="library-stats-thumb-${section_type}" class="dashboard-stats-flat svg-icon library-${section_type} hidden-xs"></div>
% endif
<div class="dashboard-stats-info-container">
<div id="library-stats-title-${section_type}" class="dashboard-stats-info-title">
<h4>${headers[section_type][0]}</h4>
@ -48,7 +55,8 @@ DOCUMENTATION :: END
<div class="dashboard-stats-info scoller-content">
<ul class="list-unstyled dashboard-stats-info-list">
% for section in data[section_type]:
<li class="dashboard-stats-info-item ${'expanded' if loop.index == 0 else ''}">
<li class="dashboard-stats-info-item ${'expanded' if loop.index == 0 else ''}" data-stat_id="${section_type}"
data-art="${section.get('art')}" data-thumb="${section.get('thumb')}">
<div class="sub-list">${loop.index + 1}</div>
<div class="sub-value">
<a href="${page('library', section['section_id'])}" title="${section['section_name']}">

View file

@ -672,7 +672,8 @@ def dbcheck():
c_db.execute(
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'server_id TEXT, section_id INTEGER, section_name TEXT, section_type TEXT, agent TEXT, '
'thumb TEXT, custom_thumb_url TEXT, art TEXT, count INTEGER, parent_count INTEGER, child_count INTEGER, '
'thumb TEXT, custom_thumb_url TEXT, art TEXT, custom_art_url TEXT, '
'count INTEGER, parent_count INTEGER, child_count INTEGER, '
'do_notify INTEGER DEFAULT 1, do_notify_created INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, '
'deleted_section INTEGER DEFAULT 0, UNIQUE(server_id, section_id))'
)
@ -1881,6 +1882,15 @@ def dbcheck():
'ALTER TABLE library_sections ADD COLUMN agent TEXT'
)
# Upgrade library_sections table from earlier versions
try:
c_db.execute('SELECT custom_art_url FROM library_sections')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table library_sections.")
c_db.execute(
'ALTER TABLE library_sections ADD COLUMN custom_art_url TEXT'
)
# Upgrade users table from earlier versions (remove UNIQUE constraint on username)
try:
result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="users"').fetchone()

View file

@ -862,7 +862,8 @@ class DataFactory(object):
try:
query = 'SELECT section_id, section_name, section_type, thumb AS library_thumb, ' \
'custom_thumb_url AS custom_thumb, art, count, parent_count, child_count ' \
'custom_thumb_url AS custom_thumb, art AS library_art, custom_art_url AS custom_art, ' \
'count, parent_count, child_count ' \
'FROM library_sections ' \
'WHERE section_id IN (%s) ' \
'ORDER BY section_type, count DESC, parent_count DESC, child_count DESC ' % ','.join(library_cards)
@ -879,11 +880,16 @@ class DataFactory(object):
else:
library_thumb = common.DEFAULT_COVER_THUMB
if item['custom_art'] and item['custom_art'] != item['library_art']:
library_art = item['custom_art']
else:
library_art = item['library_art']
library = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
'thumb': library_thumb,
'art': item['art'],
'art': library_art,
'count': item['count'],
'child_count': item['parent_count'],
'grandchild_count': item['child_count']

View file

@ -708,12 +708,14 @@ class Libraries(object):
return True
def set_config(self, section_id=None, custom_thumb='', do_notify=1, keep_history=1, do_notify_created=1):
def set_config(self, section_id=None, custom_thumb='', custom_art='',
do_notify=1, keep_history=1, do_notify_created=1):
if section_id:
monitor_db = database.MonitorDatabase()
key_dict = {'section_id': section_id}
value_dict = {'custom_thumb_url': custom_thumb,
'custom_art_url': custom_art,
'do_notify': do_notify,
'do_notify_created': do_notify_created,
'keep_history': keep_history}
@ -746,7 +748,8 @@ class Libraries(object):
try:
if str(section_id).isdigit():
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art AS library_art, ' \
'custom_art_url AS custom_art, ' \
'do_notify, do_notify_created, keep_history, deleted_section ' \
'FROM library_sections ' \
'WHERE section_id = ? '
@ -767,11 +770,16 @@ class Libraries(object):
else:
library_thumb = common.DEFAULT_COVER_THUMB
if item['custom_art'] and item['custom_art'] != item['library_art']:
library_art = item['custom_art']
else:
library_art = item['library_art']
library_details = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
'library_thumb': library_thumb,
'library_art': item['art'],
'library_art': library_art,
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],

View file

@ -526,6 +526,7 @@ class WebInterface(object):
Optional parameters:
custom_thumb (str): The URL for the custom library thumbnail
custom_art (str): The URL for the custom library background art
keep_history (int): 0 or 1
Returns:
@ -533,6 +534,7 @@ class WebInterface(object):
```
"""
custom_thumb = kwargs.get('custom_thumb', '')
custom_art = kwargs.get('custom_art', '')
do_notify = kwargs.get('do_notify', 0)
do_notify_created = kwargs.get('do_notify_created', 0)
keep_history = kwargs.get('keep_history', 0)
@ -542,6 +544,7 @@ class WebInterface(object):
library_data = libraries.Libraries()
library_data.set_config(section_id=section_id,
custom_thumb=custom_thumb,
custom_art=custom_art,
do_notify=do_notify,
do_notify_created=do_notify_created,
keep_history=keep_history)