From a31dcb5508cde585a096c0df4a27611bc39f5856 Mon Sep 17 00:00:00 2001 From: herby2212 <12448284+herby2212@users.noreply.github.com> Date: Tue, 24 Oct 2023 00:51:35 +0200 Subject: [PATCH 1/7] Quater values for History Watch Status (#2179) * initial release * change fillup orientation to clockwise * fix indentation for css * fix 50 percent circle orientation * optimize colors and padding --- data/interfaces/default/css/tautulli.css | 128 +++++++++++------- .../default/js/tables/history_table.js | 12 +- plexpy/datafactory.py | 10 +- 3 files changed, 92 insertions(+), 58 deletions(-) diff --git a/data/interfaces/default/css/tautulli.css b/data/interfaces/default/css/tautulli.css index 8cad039f..0c81f0e5 100644 --- a/data/interfaces/default/css/tautulli.css +++ b/data/interfaces/default/css/tautulli.css @@ -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 { diff --git a/data/interfaces/default/js/tables/history_table.js b/data/interfaces/default/js/tables/history_table.js index d209f90e..7f9d578f 100644 --- a/data/interfaces/default/js/tables/history_table.js +++ b/data/interfaces/default/js/tables/history_table.js @@ -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(''); + circleValue = " circle-full"; + } else if (cellData == 0.75) { + circleValue = " circle-three-quarter"; } else if (cellData == 0.5) { - $(td).html(''); - } else { - $(td).html(''); + circleValue = " circle-half"; + } else if (cellData == 0.25) { + circleValue = " circle-quarter"; } + $(td).html('
'); }, "searchable": false, "orderable": false, diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 0937480d..de3ed030 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -281,13 +281,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 From ab16adcffc77a2629663674cf83ec056f9832d42 Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:04:29 -0700 Subject: [PATCH 2/7] Add link from concurrent stream stats card to graphs page --- data/interfaces/default/graphs.html | 8 ++++++-- data/interfaces/default/home_stats.html | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/data/interfaces/default/graphs.html b/data/interfaces/default/graphs.html index 7cd0c98b..15a96a69 100644 --- a/data/interfaces/default/graphs.html +++ b/data/interfaces/default/graphs.html @@ -137,7 +137,7 @@
-
+

Daily concurrent stream count by stream type Last 30 days

@@ -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) { diff --git a/data/interfaces/default/home_stats.html b/data/interfaces/default/home_stats.html index d66dd1d4..3e1e118c 100644 --- a/data/interfaces/default/home_stats.html +++ b/data/interfaces/default/home_stats.html @@ -177,7 +177,9 @@ DOCUMENTATION :: END % elif stat_id == 'top_platforms': ${row['platform']} % elif stat_id == 'most_concurrent': - ${row['title']} + + ${row['title']} + % endif

From 98583d139ac4207604fd728f3d591c2a79cb4636 Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:05:47 -0700 Subject: [PATCH 3/7] Add config override for PMS_LANGUAGE --- plexpy/config.py | 1 + plexpy/http_handler.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plexpy/config.py b/plexpy/config.py index 6f2926d9..dbcd294d 100644 --- a/plexpy/config.py +++ b/plexpy/config.py @@ -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', ''), diff --git a/plexpy/http_handler.py b/plexpy/http_handler.py index 87c4cff5..79bb3562 100644 --- a/plexpy/http_handler.py +++ b/plexpy/http_handler.py @@ -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 From d63c0cb469375537ddb713368a1e89dde41072ad Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:24:48 -0700 Subject: [PATCH 4/7] Guard against None transcode_key --- plexpy/activity_handler.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plexpy/activity_handler.py b/plexpy/activity_handler.py index 7bfbe8fb..32f835c3 100644 --- a/plexpy/activity_handler.py +++ b/plexpy/activity_handler.py @@ -310,7 +310,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'] From c215afbf84baafb1a2020c2dc6e36944a6de1504 Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Thu, 26 Oct 2023 09:27:31 -0700 Subject: [PATCH 5/7] v2.13.2 --- CHANGELOG.md | 14 ++++++++++++++ plexpy/version.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1266e43f..d5eb4c5a 100644 --- a/CHANGELOG.md +++ b/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. diff --git a/plexpy/version.py b/plexpy/version.py index c5ee1521..5ca70297 100644 --- a/plexpy/version.py +++ b/plexpy/version.py @@ -18,4 +18,4 @@ from __future__ import unicode_literals PLEXPY_BRANCH = "master" -PLEXPY_RELEASE_VERSION = "v2.13.1" \ No newline at end of file +PLEXPY_RELEASE_VERSION = "v2.13.2" \ No newline at end of file From dd380b583f67ad112f99057da4518a3df9c7ff74 Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:05:34 -0700 Subject: [PATCH 6/7] Add system language to startup logs --- plexpy/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plexpy/__init__.py b/plexpy/__init__.py index eb1f73c2..2590c867 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -239,6 +239,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', '') )) From 32cf26884b4dcc7fa1aa26260d99689b922deedd Mon Sep 17 00:00:00 2001 From: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:05:51 -0700 Subject: [PATCH 7/7] Add system language and sqlite version to configuration table --- data/interfaces/default/configuration_table.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/data/interfaces/default/configuration_table.html b/data/interfaces/default/configuration_table.html index 676876d6..66d8ef40 100644 --- a/data/interfaces/default/configuration_table.html +++ b/data/interfaces/default/configuration_table.html @@ -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 System Timezone: ${str(plexpy.SYS_TIMEZONE)} (${'UTC{}'.format(plexpy.SYS_UTC_OFFSET)}) + + System Language: + ${plexpy.SYS_LANGUAGE + (' (override {})'.format(plexpy.CONFIG.PMS_LANGUAGE) if plexpy.CONFIG.PMS_LANGUAGE else '')} + Python Version: ${sys.version} + + SQLite Version: + ${sqlite3.sqlite_version} + Resources: