mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-21 22:03:18 -07:00
Merge branch 'nightly' of https://github.com/Tautulli/Tautulli
This commit is contained in:
commit
b536593fc1
12 changed files with 133 additions and 64 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,5 +1,19 @@
|
|||
# Changelog
|
||||
|
||||
## v2.13.2 (2023-10-26)
|
||||
* History:
|
||||
* New: Added quarter values icons for history watch status. (#2179, #2156) (Thanks @herby2212)
|
||||
* Graphs:
|
||||
* New: Added concurrent streams per day graph. (#2046) (Thanks @herby2212)
|
||||
* Exporter:
|
||||
* New: Added metadata directory to exporter fields.
|
||||
* Removed: Banner exporter fields for tv shows.
|
||||
* UI:
|
||||
* New: Added last triggered time to notification agents and newsletter agent lists.
|
||||
* Other:
|
||||
* New: Added X-Plex-Language header override to config file.
|
||||
|
||||
|
||||
## v2.13.1 (2023-08-25)
|
||||
* Notes:
|
||||
* Support for Python 3.7 has been dropped. The minimum Python version is now 3.8.
|
||||
|
|
|
@ -11,6 +11,7 @@ DOCUMENTATION :: END
|
|||
|
||||
<%!
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import plexpy
|
||||
from plexpy import common, logger
|
||||
|
@ -71,10 +72,18 @@ DOCUMENTATION :: END
|
|||
<td>System Timezone:</td>
|
||||
<td>${str(plexpy.SYS_TIMEZONE)} (${'UTC{}'.format(plexpy.SYS_UTC_OFFSET)})
|
||||
</tr>
|
||||
<tr>
|
||||
<td>System Language:</td>
|
||||
<td>${plexpy.SYS_LANGUAGE + (' (override {})'.format(plexpy.CONFIG.PMS_LANGUAGE) if plexpy.CONFIG.PMS_LANGUAGE else '')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python Version:</td>
|
||||
<td>${sys.version}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SQLite Version:</td>
|
||||
<td>${sqlite3.sqlite_version}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="top-line">Resources:</td>
|
||||
<td class="top-line">
|
||||
|
|
|
@ -338,20 +338,20 @@ object {
|
|||
}
|
||||
.btn-dark:focus,
|
||||
.btn-dark.focus {
|
||||
color: #d7d7d7;
|
||||
background-color: #3B3B3B;
|
||||
color: #d7d7d7;
|
||||
background-color: #3B3B3B;
|
||||
}
|
||||
.btn-dark:hover {
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
border-color: #444;
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
border-color: #444;
|
||||
}
|
||||
.btn-dark:active,
|
||||
.btn-dark.active,
|
||||
.open > .dropdown-toggle.btn-dark {
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
border-color: #444;
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
border-color: #444;
|
||||
}
|
||||
.btn-dark:active:hover,
|
||||
.btn-dark.active:hover,
|
||||
|
@ -362,13 +362,13 @@ object {
|
|||
.btn-dark:active.focus,
|
||||
.btn-dark.active.focus,
|
||||
.open > .dropdown-toggle.btn-dark.focus {
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
}
|
||||
.btn-dark:active,
|
||||
.btn-dark.active,
|
||||
.open > .dropdown-toggle.btn-dark {
|
||||
background-image: none;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-dark.disabled,
|
||||
.btn-dark[disabled],
|
||||
|
@ -388,8 +388,8 @@ fieldset[disabled] .btn-dark:active,
|
|||
.btn-dark.disabled.active,
|
||||
.btn-dark[disabled].active,
|
||||
fieldset[disabled] .btn-dark.active {
|
||||
background-color: #333;
|
||||
color: #aaa;
|
||||
background-color: #333;
|
||||
color: #aaa;
|
||||
}
|
||||
.btn-dark.inactive:hover {
|
||||
color: #d7d7d7;
|
||||
|
@ -398,30 +398,30 @@ fieldset[disabled] .btn-dark.active {
|
|||
cursor: default;
|
||||
}
|
||||
.btn-dark .badge {
|
||||
color: #e5e5e5;
|
||||
background-color: #3B3B3B;
|
||||
color: #e5e5e5;
|
||||
background-color: #3B3B3B;
|
||||
}
|
||||
.btn-bright {
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
}
|
||||
.btn-bright:focus,
|
||||
.btn-bright.focus {
|
||||
color: #eee;
|
||||
background-color: #eb8600;
|
||||
color: #eee;
|
||||
background-color: #eb8600;
|
||||
}
|
||||
.btn-bright:hover {
|
||||
color: #eee;
|
||||
background-color: #e59029;
|
||||
box-shadow: inset 0 1px 0 #ebac60;
|
||||
color: #eee;
|
||||
background-color: #e59029;
|
||||
box-shadow: inset 0 1px 0 #ebac60;
|
||||
}
|
||||
.btn-bright:active,
|
||||
.btn-bright.active,
|
||||
.open > .dropdown-toggle.btn-bright {
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
}
|
||||
.btn-bright:active:hover,
|
||||
.btn-bright.active:hover,
|
||||
|
@ -432,14 +432,14 @@ fieldset[disabled] .btn-dark.active {
|
|||
.btn-bright:active.focus,
|
||||
.btn-bright.active.focus,
|
||||
.open > .dropdown-toggle.btn-bright.focus {
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
}
|
||||
.btn-bright:active,
|
||||
.btn-bright.active,
|
||||
.open > .dropdown-toggle.btn-bright {
|
||||
background-image: none;
|
||||
background-image: none;
|
||||
}
|
||||
.btn-bright.disabled,
|
||||
.btn-bright[disabled],
|
||||
|
@ -459,13 +459,13 @@ fieldset[disabled] .btn-bright:active,
|
|||
.btn-bright.disabled.active,
|
||||
.btn-bright[disabled].active,
|
||||
fieldset[disabled] .btn-bright.active {
|
||||
background-color: #cc7b19;
|
||||
border-color: #b56d16;
|
||||
background-color: #cc7b19;
|
||||
border-color: #b56d16;
|
||||
}
|
||||
.btn-bright .badge {
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
box-shadow: inset 0 1px 0 #e7993b;
|
||||
}
|
||||
.btn-danger.btn-edit {
|
||||
color: #d7d7d7;
|
||||
|
@ -479,14 +479,14 @@ fieldset[disabled] .btn-bright.active {
|
|||
border-color: #ac2925;
|
||||
}
|
||||
.btn-danger.btn-edit.active {
|
||||
color: #eee;
|
||||
background-color: #c9302c;
|
||||
border-color: #ac2925;
|
||||
color: #eee;
|
||||
background-color: #c9302c;
|
||||
border-color: #ac2925;
|
||||
}
|
||||
.btn-danger.btn-edit.active:hover {
|
||||
color: #eee;
|
||||
background-color: #ac2925;
|
||||
border-color: #761c19;
|
||||
color: #eee;
|
||||
background-color: #ac2925;
|
||||
border-color: #761c19;
|
||||
}
|
||||
.btn-group select {
|
||||
margin-top: 0;
|
||||
|
@ -667,12 +667,12 @@ textarea.form-control:focus {
|
|||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
-ms-touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
background-image: none;
|
||||
background-color: #3B3B3B;
|
||||
color: #e5e5e5;
|
||||
|
@ -690,10 +690,10 @@ textarea.form-control:focus {
|
|||
}
|
||||
.btn-filter.active,
|
||||
.btn-filter.active.focus {
|
||||
background-color: #b7800a !important;
|
||||
background-color: #b7800a !important;
|
||||
}
|
||||
.btn-filter.active:hover {
|
||||
background-color: #896007 !important;
|
||||
background-color: #896007 !important;
|
||||
}
|
||||
.form-control-feedback {
|
||||
color: #E5A00D;
|
||||
|
@ -1281,7 +1281,7 @@ a .dashboard-activity-metadata-user-thumb:hover {
|
|||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
z-index: 1;
|
||||
-webkit-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
-moz-border-radius: 50%;
|
||||
border-radius: 350%;
|
||||
overflow: hidden;
|
||||
|
@ -2203,8 +2203,8 @@ span.settings-warning {
|
|||
padding-left: 10px;
|
||||
}
|
||||
#menu_link_show_advanced_settings.active {
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
color: #eee;
|
||||
background-color: #cc7b19;
|
||||
}
|
||||
#configUpdate .form-group,
|
||||
#configUpdate .checkbox{
|
||||
|
@ -2854,6 +2854,30 @@ a .home-platforms-list-cover-face:hover
|
|||
overflow: hidden;
|
||||
max-width: 350px;
|
||||
}
|
||||
.circle {
|
||||
width: 1.55rem;
|
||||
height: 1.55rem;
|
||||
border-radius: 50%;
|
||||
border: 0.2rem solid #eeeeee;
|
||||
}
|
||||
.circle-quarter {
|
||||
background-image:
|
||||
linear-gradient(00deg, #2b2b2b 50%, transparent 50%),
|
||||
linear-gradient(270deg, #eeeeee 50%, transparent 50%);
|
||||
}
|
||||
.circle-half {
|
||||
background-image:
|
||||
linear-gradient(90deg, #2b2b2b 50%, transparent 50%),
|
||||
linear-gradient(-90deg, #eeeeee 50%, transparent 50%);
|
||||
}
|
||||
.circle-three-quarter {
|
||||
background-image:
|
||||
linear-gradient(180deg, transparent 50%, #eeeeee 50%),
|
||||
linear-gradient(-90deg, #eeeeee 50%, transparent 50%);
|
||||
}
|
||||
.circle-full {
|
||||
background: #eeeeee;
|
||||
}
|
||||
#graph-tabs {
|
||||
padding-bottom: 10px;
|
||||
float: none;
|
||||
|
@ -2991,8 +3015,8 @@ a .home-platforms-list-cover-face:hover
|
|||
border-left: 2px solid #444;
|
||||
border-top: 1px solid #2d2d2d;
|
||||
-webkit-transition: all 0.3s ease;
|
||||
-o-transition: all 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
-o-transition: all 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.stacked-configs > li > span:hover,
|
||||
.stacked-configs > li > span:focus {
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="row" id="concurrent-graph">
|
||||
<div class="col-md-12">
|
||||
<h4><i class="fa fa-video-camera"></i> Daily concurrent stream count</span> by stream type <small>Last <span class="days">30</span> days</small></h4>
|
||||
<p class="help-block">
|
||||
|
@ -372,6 +372,10 @@
|
|||
break
|
||||
}
|
||||
|
||||
if (window.location.hash === '#concurrent-graph') {
|
||||
current_tab = '#tabs-stream';
|
||||
}
|
||||
|
||||
$('#yaxis-' + yaxis).prop('checked', true);
|
||||
$('#yaxis-' + yaxis).closest('label').addClass('active');
|
||||
$('#graph-days').val(current_day_range);
|
||||
|
@ -639,7 +643,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
$('#nav-tabs-2').tab('show');
|
||||
$('#nav-tabs-stream').tab('show');
|
||||
}
|
||||
|
||||
function loadGraphsTab3(time_range, yaxis) {
|
||||
|
|
|
@ -177,7 +177,9 @@ DOCUMENTATION :: END
|
|||
% elif stat_id == 'top_platforms':
|
||||
${row['platform']}
|
||||
% elif stat_id == 'most_concurrent':
|
||||
${row['title']}
|
||||
<a href="graphs#concurrent-graph" title="${row['title']}">
|
||||
${row['title']}
|
||||
</a>
|
||||
% endif
|
||||
</div>
|
||||
<div class="sub-count">
|
||||
|
|
|
@ -263,13 +263,17 @@ history_table_options = {
|
|||
"targets": [12],
|
||||
"data": "watched_status",
|
||||
"createdCell": function (td, cellData, rowData, row, col) {
|
||||
var circleValue = "";
|
||||
if (cellData == 1) {
|
||||
$(td).html('<span class="watched-tooltip" data-toggle="tooltip" title="' + rowData['percent_complete'] + '%"><i class="fa fa-lg fa-circle"></i></span>');
|
||||
circleValue = " circle-full";
|
||||
} else if (cellData == 0.75) {
|
||||
circleValue = " circle-three-quarter";
|
||||
} else if (cellData == 0.5) {
|
||||
$(td).html('<span class="watched-tooltip" data-toggle="tooltip" title="' + rowData['percent_complete'] + '%"><i class="fa fa-lg fa-adjust fa-rotate-180"></i></span>');
|
||||
} else {
|
||||
$(td).html('<span class="watched-tooltip" data-toggle="tooltip" title="' + rowData['percent_complete'] + '%"><i class="fa fa-lg fa-circle-o"></i></span>');
|
||||
circleValue = " circle-half";
|
||||
} else if (cellData == 0.25) {
|
||||
circleValue = " circle-quarter";
|
||||
}
|
||||
$(td).html('<span class="watched-tooltip" data-toggle="tooltip" title="' + rowData['percent_complete'] + '%"><div class="circle' + circleValue + '" /></span>');
|
||||
},
|
||||
"searchable": false,
|
||||
"orderable": false,
|
||||
|
|
|
@ -236,6 +236,9 @@ def initialize(config_file):
|
|||
logger.info("{} (UTC{})".format(
|
||||
str(SYS_TIMEZONE), SYS_UTC_OFFSET
|
||||
))
|
||||
logger.info("Language {}{} / Encoding {}".format(
|
||||
SYS_LANGUAGE, f' (override {CONFIG.PMS_LANGUAGE})' if CONFIG.PMS_LANGUAGE else '', SYS_ENCODING
|
||||
))
|
||||
logger.info("Python {}".format(
|
||||
sys.version.replace('\n', '')
|
||||
))
|
||||
|
|
|
@ -311,7 +311,9 @@ class ActivityHandler(object):
|
|||
last_state = self.db_session['state']
|
||||
last_rating_key = str(self.db_session['rating_key'])
|
||||
last_live_uuid = self.db_session['live_uuid']
|
||||
last_transcode_key = self.db_session['transcode_key'].split('/')[-1]
|
||||
last_transcode_key = self.db_session['transcode_key']
|
||||
if isinstance(last_transcode_key, str):
|
||||
last_transcode_key = last_transcode_key.split('/')[-1]
|
||||
last_paused = self.db_session['last_paused']
|
||||
last_rating_key_websocket = self.db_session['rating_key_websocket']
|
||||
last_guid = self.db_session['guid']
|
||||
|
|
|
@ -55,6 +55,7 @@ _CONFIG_DEFINITIONS = {
|
|||
'PMS_IP': (str, 'PMS', '127.0.0.1'),
|
||||
'PMS_IS_CLOUD': (int, 'PMS', 0),
|
||||
'PMS_IS_REMOTE': (int, 'PMS', 0),
|
||||
'PMS_LANGUAGE': (str, 'PMS', ''),
|
||||
'PMS_LOGS_FOLDER': (str, 'PMS', ''),
|
||||
'PMS_LOGS_LINE_CAP': (int, 'PMS', 1000),
|
||||
'PMS_NAME': (str, 'PMS', ''),
|
||||
|
|
|
@ -283,13 +283,19 @@ class DataFactory(object):
|
|||
if item['live']:
|
||||
item['percent_complete'] = 100
|
||||
|
||||
base_watched_value = watched_percent[item['media_type']] / 4.0
|
||||
|
||||
if helpers.check_watched(
|
||||
item['media_type'], item['view_offset'], item['duration'],
|
||||
item['marker_credits_first'], item['marker_credits_final']
|
||||
):
|
||||
watched_status = 1
|
||||
elif item['percent_complete'] >= watched_percent[item['media_type']] / 2.0:
|
||||
watched_status = 0.5
|
||||
elif item['percent_complete'] >= base_watched_value * 3.0:
|
||||
watched_status = 0.75
|
||||
elif item['percent_complete'] >= base_watched_value * 2.0:
|
||||
watched_status = 0.50
|
||||
elif item['percent_complete'] >= base_watched_value:
|
||||
watched_status = 0.25
|
||||
else:
|
||||
watched_status = 0
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ class HTTPHandler(object):
|
|||
plexpy.common.PLATFORM_RELEASE),
|
||||
'X-Plex-Device-Name': '{} ({})'.format(plexpy.common.PLATFORM_DEVICE_NAME,
|
||||
plexpy.common.PRODUCT),
|
||||
'Accept-Language': plexpy.SYS_LANGUAGE
|
||||
'X-Plex-Language': plexpy.CONFIG.PMS_LANGUAGE or plexpy.SYS_LANGUAGE
|
||||
}
|
||||
|
||||
self.token = token
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
PLEXPY_BRANCH = "master"
|
||||
PLEXPY_RELEASE_VERSION = "v2.13.1"
|
||||
PLEXPY_RELEASE_VERSION = "v2.13.2"
|
Loading…
Add table
Add a link
Reference in a new issue