Compare commits

..

15 Commits

Author SHA1 Message Date
JonnyWong16
70b6bd4efd v2.1.13 2018-06-16 16:42:20 -07:00
JonnyWong16
4f4a99d695 Fix soft crash when viewing photos not in an album 2018-06-16 16:38:06 -07:00
JonnyWong16
f65baa22f1 Fix font awesome icon in setting alerts 2018-06-12 19:28:33 -07:00
JonnyWong16
a1fb081d47 Fix font awesome info page breadcrumb icon 2018-06-11 11:36:50 -07:00
JonnyWong16
63ac3eec98 Fix font awesome remove ajax loader icon 2018-06-11 11:30:51 -07:00
JonnyWong16
73c11c053d Add clip to notification param media type example 2018-06-11 11:11:51 -07:00
JonnyWong16
85c398ce05 Change graph resolution font awesome icon 2018-06-10 19:55:31 -07:00
JonnyWong16
7387cb8322 Add date and time parameters for notifications and newsletters 2018-06-10 19:48:46 -07:00
JonnyWong16
37841b6e8c Fix font awesome icons in notifier text accordions 2018-06-10 19:36:32 -07:00
JonnyWong16
af1355e220 Fix blank font awesome icons 2018-06-10 18:23:22 -07:00
JonnyWong16
37bd005907 Update Discord links 2018-06-10 10:48:05 -07:00
JonnyWong16
311030b58e Add buttons to Discord/Reddit on support page 2018-06-10 10:47:48 -07:00
JonnyWong16
bdd124327f Update to Font Awesome v5 2018-06-10 10:15:49 -07:00
JonnyWong16
70e5e698fa Add support page 2018-06-09 21:28:40 -07:00
JonnyWong16
33e799955e Correct sessions.product column type 2018-06-09 00:03:23 -07:00
24 changed files with 284 additions and 100 deletions

View File

@@ -1,5 +1,15 @@
# Changelog # Changelog
## v2.1.13 (2018-06-16)
* Monitoring:
* Fix: Soft crash when viewing photos not in an album.
* Notifications:
* New: Added current date and time notification parameters.
* UI:
* New: Added support page with embedded Discord chat using WidgetBot.
## v2.1.12 (2018-06-08) ## v2.1.12 (2018-06-08)
* Notifications: * Notifications:

View File

@@ -1,6 +1,6 @@
# Tautulli # Tautulli
[![Discord](https://img.shields.io/badge/Discord-Tautulli-7289DA.svg?style=flat-square)](https://discord.gg/tQcWEUp) [![Discord](https://img.shields.io/badge/Discord-Tautulli-7289DA.svg?style=flat-square)](https://tautulli.com/discord)
[![Reddit](https://img.shields.io/badge/Reddit-Tautulli-FF5700.svg?style=flat-square)](https://www.reddit.com/r/Tautulli/) [![Reddit](https://img.shields.io/badge/Reddit-Tautulli-FF5700.svg?style=flat-square)](https://www.reddit.com/r/Tautulli/)
[![Plex Forums](https://img.shields.io/badge/Plex%20Forums-Tautulli-E5A00D.svg?style=flat-square)](https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server) [![Plex Forums](https://img.shields.io/badge/Plex%20Forums-Tautulli-E5A00D.svg?style=flat-square)](https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server)
@@ -35,7 +35,7 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
* Read the [Installation Guides](https://github.com/Tautulli/Tautulli-Wiki/wiki/Installation) for instructions to install Tautulli. * Read the [Installation Guides](https://github.com/Tautulli/Tautulli-Wiki/wiki/Installation) for instructions to install Tautulli.
* The [Frequently Asked Questions](https://github.com/Tautulli/Tautulli-Wiki/wiki/Frequently-Asked-Questions) in the wiki can help you with common problems. * The [Frequently Asked Questions](https://github.com/Tautulli/Tautulli-Wiki/wiki/Frequently-Asked-Questions) in the wiki can help you with common problems.
* Support is available on [Discord](https://discord.gg/tQcWEUp), [Reddit](https://www.reddit.com/r/Tautulli), or the [Plex Forums](https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server). * Support is available on [Discord](https://tautulli.com/discord), [Reddit](https://www.reddit.com/r/Tautulli), or the [Plex Forums](https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server).
## Issues & Feature Requests ## Issues & Feature Requests

View File

@@ -17,7 +17,6 @@
<link href="${http_root}css/pnotify.custom.min.css" rel="stylesheet" /> <link href="${http_root}css/pnotify.custom.min.css" rel="stylesheet" />
<link href="${http_root}css/tautulli.css${cache_param}" rel="stylesheet"> <link href="${http_root}css/tautulli.css${cache_param}" rel="stylesheet">
<link href="${http_root}css/opensans.min.css" rel="stylesheet"> <link href="${http_root}css/opensans.min.css" rel="stylesheet">
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
${next.headIncludes()} ${next.headIncludes()}
<!-- Favicons --> <!-- Favicons -->
@@ -134,7 +133,7 @@
<li role="separator" class="divider"></li> <li role="separator" class="divider"></li>
<li><a href="logs"><i class="fa fa-fw fa-list-alt"></i> View Logs</a></li> <li><a href="logs"><i class="fa fa-fw fa-list-alt"></i> View Logs</a></li>
<li><a href="${anon_url('https://github.com/%s/%s-Wiki/wiki/Frequently-Asked-Questions' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}" target="_blank"><i class="fa fa-fw fa-question-circle"></i> FAQ</a></li> <li><a href="${anon_url('https://github.com/%s/%s-Wiki/wiki/Frequently-Asked-Questions' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}" target="_blank"><i class="fa fa-fw fa-question-circle"></i> FAQ</a></li>
<li><a href="settings?support=true"><i class="fa fa-fw fa-comment"></i> Support</a></li> <li><a href="support"><i class="fa fa-fw fa-comment"></i> Support</a></li>
<li role="separator" class="divider"></li> <li role="separator" class="divider"></li>
<li><a href="#" data-target="#donate-modal" data-toggle="modal"><i class="fa fa-fw fa-heart"></i> Donate</a></li> <li><a href="#" data-target="#donate-modal" data-toggle="modal"><i class="fa fa-fw fa-heart"></i> Donate</a></li>
<li role="separator" class="divider"></li> <li role="separator" class="divider"></li>
@@ -289,6 +288,9 @@ ${next.modalIncludes()}
<script src="${http_root}js/jquery-2.1.4.min.js"></script> <script src="${http_root}js/jquery-2.1.4.min.js"></script>
<script src="${http_root}js/bootstrap.min.js"></script> <script src="${http_root}js/bootstrap.min.js"></script>
<script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script> <script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script>
<script>window.FontAwesomeConfig = {searchPseudoElements: true}</script>
<script src="${http_root}js/fontawesome-v5.0.13.min.js"></script>
<script src="${http_root}js/fontawesome-v4-shims.min.js"></script>
<script src="${http_root}js/pnotify.custom.min.js"></script> <script src="${http_root}js/pnotify.custom.min.js"></script>
<script src="${http_root}js/script.js${cache_param}"></script> <script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/jquery.qrcode.min.js"></script> <script src="${http_root}js/jquery.qrcode.min.js"></script>

View File

@@ -88,7 +88,7 @@ DOCUMENTATION :: END
<tr> <tr>
<td>Support:</td> <td>Support:</td>
<td> <td>
<a class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/tQcWEUp')}" target="_blank">Tautulli Discord Server</a> | <a class="no-highlight support-modal-link" href="${anon_url('https://tautulli.com/discord')}" target="_blank">Tautulli Discord Server</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://www.reddit.com/r/Tautulli')}" target="_blank">Tautulli Subreddit</a> | <a class="no-highlight support-modal-link" href="${anon_url('https://www.reddit.com/r/Tautulli')}" target="_blank">Tautulli Subreddit</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server')}" target="_blank">Plex Forums</a> <a class="no-highlight support-modal-link" href="${anon_url('https://forums.plex.tv/discussion/307821/tautulli-monitor-your-plex-media-server')}" target="_blank">Plex Forums</a>
</td> </td>

View File

@@ -113,6 +113,10 @@ div.form-control .selectize-input {
.wizard-input-section .selectize-dropdown.form-control.selectize-pms-ip { .wizard-input-section .selectize-dropdown.form-control.selectize-pms-ip {
margin-top: 0 !important; margin-top: 0 !important;
} }
#condition-widget .fa-plus,
#condition-widget .fa-minus {
cursor: pointer;
}
.react-selectize.root-node .react-selectize-control .react-selectize-placeholder { .react-selectize.root-node .react-selectize-control .react-selectize-placeholder {
color: #fff !important; color: #fff !important;
} }
@@ -1599,10 +1603,8 @@ a:hover .dashboard-recent-media-cover {
margin: 0; margin: 0;
background: none; background: none;
} }
.summary-navbar-list .breadcrumb > li + li:before { .summary-navbar-list .breadcrumb > .breadcrumb-arrow {
color: #444; color: #444;
font-family: FontAwesome;
content: "\f054";
padding: 0 15px; padding: 0 15px;
} }
.summary-navbar-list .breadcrumb > .active { .summary-navbar-list .breadcrumb > .active {
@@ -2113,21 +2115,18 @@ a:hover .item-children-poster {
} }
.settings-alert ul li { .settings-alert ul li {
list-style: none; list-style: none;
padding: 5px 12px 5px 35px; padding: 5px 12px;
margin: 0; margin: 0;
border: 1px solid #ebccd1; border: 1px solid #ebccd1;
border-radius: 4px; border-radius: 4px;
} }
.settings-alert ul li:before { .settings-alert ul li:before {
content: "\f071"; display: none;
font-family: FontAwesome; content: "\f071 ";
font-style: normal; font-family: "Font Awesome 5 Solid";
font-weight: normal; }
text-decoration: inherit; .settings-alert ul li .svg-inline--fa {
font-size: 18px; margin-right: 5px;
position: absolute;
top: 5px;
left: 12px;
} }
.settings-warning { .settings-warning {
color: #eb8600; color: #eb8600;
@@ -2957,10 +2956,13 @@ a .home-platforms-list-cover-face:hover
background: #282828; background: #282828;
list-style: none; list-style: none;
} }
.accordion .link { .accordion li {
margin: 0;
}
.accordion li .link {
cursor: pointer; cursor: pointer;
display: block; display: block;
padding: 8px 20px 8px 30px; padding: 8px 12px 8px 12px;
color: #999; color: #999;
border-bottom: 1px solid #2d2d2d; border-bottom: 1px solid #2d2d2d;
position: relative; position: relative;
@@ -2968,37 +2970,28 @@ a .home-platforms-list-cover-face:hover
-o-transition: all 0.3s ease; -o-transition: all 0.3s ease;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.accordion li { .accordion li .link:hover {
margin: 0; color: #fff;
background: #2f2f2f;
}
.accordion li .link span.toggle-right {
float: right;
padding-left: 10px;
} }
.accordion li:last-child .link { .accordion li:last-child .link {
border-bottom: 0; border-bottom: 0;
} }
.accordion li i.fa { .accordion li .fa-chevron-down {
position: absolute;
top: 10px;
left: 10px;
color: #999; color: #999;
-webkit-transition: all 0.3s ease; -webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease; -o-transition: all 0.3s ease;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.accordion li i.fa-chevron-down {
right: 12px;
left: auto;
font-size: 16px;
}
.accordion li .link:hover {
color: #FFF;
background: #2f2f2f;
}
.accordion li.open .link { .accordion li.open .link {
color: #f9be03; color: #f9be03;
} }
.accordion li.open i { .accordion li.open .fa-chevron-down {
color: #f9be03; color: #f9be03;
}
.accordion li.open i.fa-chevron-down {
-webkit-transform: rotate(180deg); -webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg); -ms-transform: rotate(180deg);
-o-transform: rotate(180deg); -o-transform: rotate(180deg);
@@ -3156,34 +3149,6 @@ div.dataTables_info {
-o-transition: none !important; -o-transition: none !important;
transition: none !important; transition: none !important;
} }
.settings-alert {
float: left;
padding: 0;
margin: 5px 0;
border: 0;
position: relative;
}
.settings-alert ul {
padding: 0;
}
.settings-alert ul li {
list-style: none;
padding: 5px 12px 5px 35px;
margin: 0;
border: 1px solid #ebccd1;
border-radius: 4px;
}
.settings-alert ul li:before {
content: "\f071";
font-family: FontAwesome;
font-style: normal;
font-weight: normal;
text-decoration: inherit;
font-size: 18px;
position: absolute;
top: 5px;
left: 12px;
}
#users-to-delete > li, #users-to-delete > li,
#users-to-purge > li, #users-to-purge > li,
#libraries-to-delete > li, #libraries-to-delete > li,
@@ -4096,3 +4061,62 @@ a[data-tab-destination] {
.pointer { .pointer {
cursor: pointer; cursor: pointer;
} }
.iframe-container {
width: 100%;
height: calc(100vh - 200px);
position: relative;
}
.iframe-overlay {
width: 100%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: url(../images/discord-overlay.png) no-repeat;
background-size: cover;
border: 1px solid #36393e;
}
.iframe-button-container {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.iframe-button {
color: #fff;
border-radius: 20px;
text-align: center;
cursor: pointer;
font-size: 15px;
height: 28px;
line-height: 28px;
min-width: 200px;
transition: box-shadow 0.3s ease;
padding: 0 15px;
background: rgba(114, 137, 218, 0.4);
text-transform: uppercase;
text-decoration: none;
display: block;
}
.iframe-button:hover,
.iframe-button:focus {
color: #fff;
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 0px 99999px inset, rgba(0, 0, 0, 0.2) 0px 1px 5px 0px, rgba(0, 0, 0, 0.14) 0px 2px 2px 0px, rgba(0, 0, 0, 0.12) 0px 3px 1px -2px;
}
.iframe-button:active {
box-shadow: rgba(255, 255, 255, 0.1) 0px 0px 0px 99999px inset, rgba(0, 0, 0, 0.2) 0px 5px 5px -3px, rgba(0, 0, 0, 0.14) 0px 8px 10px 1px, rgba(0, 0, 0, 0.12) 0px 3px 14px 2px;
}
.iframe {
width: 100%;
height: 100%;
position: inherit;
display: block;
border: 0;
}
.fa-blank {
visibility: hidden;
}

View File

@@ -168,7 +168,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h4><i class="fa fa-expand"></i> <span class="yaxis-text">Play count</span> by source resolution <small>Last <span class="days">30</span> days</small></h4> <h4><i class="fa fa-expand-arrows-alt"></i> <span class="yaxis-text">Play count</span> by source resolution <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block"> <p class="help-block">
The combined total of tv and movies by their original resolution (pre-transcoding). The combined total of tv and movies by their original resolution (pre-transcoding).
</p> </p>
@@ -181,7 +181,7 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h4><i class="fa fa-expand"></i> <span class="yaxis-text">Play count</span> by stream resolution <small>Last <span class="days">30</span> days</small></h4> <h4><i class="fa fa-expand-arrows-alt"></i> <span class="yaxis-text">Play count</span> by stream resolution <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block"> <p class="help-block">
The combined total of tv and movies by their streamed resolution (post-transcoding). The combined total of tv and movies by their streamed resolution (post-transcoding).
</p> </p>

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

View File

@@ -83,30 +83,43 @@ DOCUMENTATION :: END
<ul class="list-unstyled breadcrumb"> <ul class="list-unstyled breadcrumb">
% if data['media_type'] in ('movie', 'collection'): % if data['media_type'] in ('movie', 'collection'):
<li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li> <li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'show': % elif data['media_type'] == 'show':
<li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li> <li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'season': % elif data['media_type'] == 'season':
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li> <li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Season ${data['media_index']}</li> <li class="active metadata-xml">Season ${data['media_index']}</li>
% elif data['media_type'] == 'episode': % elif data['media_type'] == 'episode':
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li> <li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="info?rating_key=${data['parent_rating_key']}">Season ${data['parent_media_index']}</a></li> <li><a href="info?rating_key=${data['parent_rating_key']}">Season ${data['parent_media_index']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Episode ${data['media_index']} - ${data['title']}</li> <li class="active metadata-xml">Episode ${data['media_index']} - ${data['title']}</li>
% elif data['media_type'] == 'artist': % elif data['media_type'] == 'artist':
<li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li> <li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'album': % elif data['media_type'] == 'album':
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li> <li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li> <li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'track': % elif data['media_type'] == 'track':
<li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li> <li class="hidden-xs hidden-sm"><a href="library?section_id=${data['section_id']}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li> <li class="hidden-xs hidden-sm"><a href="info?rating_key=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li> <li><a href="info?rating_key=${data['parent_rating_key']}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Track ${data['media_index']} - ${data['title']}</li> <li class="active metadata-xml">Track ${data['media_index']} - ${data['title']}</li>
% endif % endif
</ul> </ul>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -37,7 +37,7 @@ function showMsg(msg, loader, timeout, ms, error) {
} }
var message = $("<div class='msg'>" + msg + "</div>"); var message = $("<div class='msg'>" + msg + "</div>");
if (loader) { if (loader) {
message = $("<i class='fa fa-refresh fa-spin'></i> " + msg + "</div>"); message = $("<div class='msg'><i class='fa fa-refresh fa-spin'></i> " + msg + "</div>");
feedback.css("padding", "14px 10px"); feedback.css("padding", "14px 10px");
} }
if (error) { if (error) {
@@ -103,14 +103,14 @@ function doAjaxCall(url, elem, reload, form, showMsg, callback) {
dataString = $(formID).serialize(); dataString = $(formID).serialize();
} }
// Loader Image // Loader Image
var loader = $("<i class='fa fa-refresh fa-spin'></i>"); var loader = $("<i class='fa fa-refresh fa-spin ajaxLoader-" + url +"></i>");
// Data Success Message // Data Success Message
var dataSucces = $(elem).data('success'); var dataSucces = $(elem).data('success');
if (typeof dataSucces === "undefined") { if (typeof dataSucces === "undefined") {
// Standard Message when variable is not set // Standard Message when variable is not set
dataSucces = "Success!"; dataSucces = "Success!";
} }
// Data Errror Message // Data Error Message
var dataError = $(elem).data('error'); var dataError = $(elem).data('error');
if (typeof dataError === "undefined") { if (typeof dataError === "undefined") {
// Standard Message when variable is not set // Standard Message when variable is not set
@@ -187,7 +187,7 @@ function doAjaxCall(url, elem, reload, form, showMsg, callback) {
}, },
complete: function (jqXHR, textStatus) { complete: function (jqXHR, textStatus) {
// Remove loaders and stuff, ajax request is complete! // Remove loaders and stuff, ajax request is complete!
loader.remove(); feedback.remove('.ajaxLoader-' + url);
if (typeof callback === "function") { if (typeof callback === "function") {
callback(jqXHR); callback(jqXHR);
} }

View File

@@ -67,7 +67,7 @@ history_table_options = {
expand_history = '<span class="expand-history-tooltip" data-toggle="tooltip" title="Show Detailed History"><i class="fa fa-plus-circle fa-fw"></i></span>'; expand_history = '<span class="expand-history-tooltip" data-toggle="tooltip" title="Show Detailed History"><i class="fa fa-plus-circle fa-fw"></i></span>';
$(td).html('<div><a href="#"><div style="float: left;">' + expand_history + '&nbsp;' + date + '</div></a></div>'); $(td).html('<div><a href="#"><div style="float: left;">' + expand_history + '&nbsp;' + date + '</div></a></div>');
} else { } else {
$(td).html('<div style="float: left;"><i class="fa fa-fw"></i>&nbsp;' + date + '</div>'); $(td).html('<div style="float: left;"><i class="fa fa-plus-circle fa-fw fa-blank">&nbsp;</i>&nbsp;' + date + '</div>');
} }
}, },
"searchable": false, "searchable": false,

View File

@@ -58,7 +58,7 @@ media_info_table_options = {
expand_details = '<span class="expand-media-info-tooltip" data-toggle="tooltip" title="Show Photos"><i class="fa fa-plus-circle fa-fw"></i></span>'; 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 + '&nbsp;' + date + '</div></a></div>'); $(td).html('<div><a href="#"><div style="float: left;">' + expand_details + '&nbsp;' + date + '</div></a></div>');
} else { } else {
$(td).html('<div style="float: left;"><i class="fa fa-fw"></i>&nbsp;' + date + '</div>'); $(td).html('<div style="float: left;"><i class="fa fa-plus-circle fa-fw fa-blank"></i>&nbsp;' + date + '</div>');
} }
} }
}, },

View File

@@ -202,7 +202,11 @@
% if notifier['agent_name'] == 'scripts': % if notifier['agent_name'] == 'scripts':
% for action in available_notification_actions: % for action in available_notification_actions:
<li> <li>
<div class="link"><i class="fa ${action['icon']} fa-fw"></i>&nbsp;${action['label']}<i class="fa fa-chevron-down"></i></div> <div class="link">
<span class="toggle-left"><i class="fa ${action['icon']} fa-fw"></i></span>&nbsp;
${action['label']}
<span class="toggle-right"><i class="fa fa-chevron-down"></i></span>
</div>
<ul class="submenu"> <ul class="submenu">
<li> <li>
<div class="form-group"> <div class="form-group">
@@ -224,7 +228,11 @@
% else: % else:
% for action in available_notification_actions: % for action in available_notification_actions:
<li> <li>
<div class="link"><i class="fa ${action['icon']} fa-fw"></i>&nbsp;${action['label']}<i class="fa fa-chevron-down"></i></div> <div class="link">
<span class="toggle-left"><i class="fa ${action['icon']} fa-fw"></i></span>&nbsp;
${action['label']}
<span class="toggle-right"><i class="fa fa-chevron-down"></i></span>
</div>
<ul class="submenu"> <ul class="submenu">
<li> <li>
<div class="form-group"> <div class="form-group">

View File

@@ -1763,9 +1763,6 @@
} else if ("${kwargs.get('reinstall_geoip')}" == 'true') { } else if ("${kwargs.get('reinstall_geoip')}" == 'true') {
$('#reinstall_geoip_db').removeClass('no-highlight').css('color','#e9a049'); $('#reinstall_geoip_db').removeClass('no-highlight').css('color','#e9a049');
} }
if ("${kwargs.get('support')}" == 'true') {
$('.support-modal-link').removeClass('no-highlight').css('color','#e9a049');
}
} }
}); });
} }

View File

@@ -0,0 +1,68 @@
<%inherit file="base.html"/>
<%!
from plexpy.helpers import anon_url
%>
<%def name="headIncludes()">
</%def>
<%def name="headerIncludes()">
</%def>
<%def name="body()">
<div class='container-fluid'>
<div class='table-card-header'>
<div class="header-bar">
<span><i class="fa fa-comment"></i> Support</span>
</div>
<div class="button-bar">
<div class="btn-group">
<a class="btn btn-dark" href="${anon_url('https://tautulli.com/discord')}" target="_blank"><i class="fab fa-discord"></i>&nbsp; Join Discord</a>
</div>
<div class="btn-group">
<a class="btn btn-dark" href="${anon_url('https://www.reddit.com/r/Tautulli')}" target="_blank"><i class="fab fa-reddit"></i>&nbsp; Join Reddit</a>
</div>
<div class="btn-group">
<button class="btn btn-dark" id="popout-iframe-button"><i class="fa fa-external-link"></i> Pop Out Chat</button>
</div>
</div>
</div>
<div class='table-card-back'>
<div class="iframe-container">
<iframe class="iframe" allowfullscreen="true" id="support-iframe" data-name="Tautulli-Support" data-src="https://support.tautulli.com"
sandbox="allow-presentation allow-forms allow-same-origin allow-pointer-lock allow-scripts allow-popups allow-modals allow-top-navigation"
style="display: none;">
</iframe>
<div class="iframe-overlay">
<div class="iframe-button-container">
<a class="iframe-button">Start chatting now</a>
</div>
</div>
</div>
</div>
</div>
</%def>
<%def name="modalIncludes()">
</%def>
<%def name="javascriptIncludes()">
<script>
var popout_chat;
$('.iframe-button').click(function () {
if (popout_chat) {
popout_chat.close();
}
var iframe = $('#support-iframe');
iframe.attr('src', iframe.data('src')).fadeIn();
$('.iframe-overlay').fadeOut();
});
$('#popout-iframe-button').click(function () {
var iframe = $('#support-iframe');
popout_chat = window.open(iframe.data('src'), 'Tautulli-Discord-Support', 'width=1280,height=720');
iframe.attr('src', '').fadeOut();
$('.iframe-overlay').fadeIn();
});
</script>
</%def>

View File

@@ -934,7 +934,7 @@ def dbcheck():
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN product INTEGER' 'ALTER TABLE sessions ADD COLUMN product TEXT'
) )
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN optimized_version INTEGER' 'ALTER TABLE sessions ADD COLUMN optimized_version INTEGER'

View File

@@ -307,10 +307,17 @@ NOTIFICATION_PARAMETERS = [
{'name': 'Server Version', 'type': 'str', 'value': 'server_version', 'description': 'The current version of your Plex Server.'}, {'name': 'Server Version', 'type': 'str', 'value': 'server_version', 'description': 'The current version of your Plex Server.'},
{'name': 'Server ID', 'type': 'str', 'value': 'server_machine_id', 'description': 'The unique identifier for your Plex Server.'}, {'name': 'Server ID', 'type': 'str', 'value': 'server_machine_id', 'description': 'The unique identifier for your Plex Server.'},
{'name': 'Action', 'type': 'str', 'value': 'action', 'description': 'The action that triggered the notification.'}, {'name': 'Action', 'type': 'str', 'value': 'action', 'description': 'The action that triggered the notification.'},
{'name': 'Week Number', 'type': 'int', 'value': 'week_number', 'description': 'The week number of the year when the notfication was triggered.'}, {'name': 'Current Year', 'type': 'int', 'value': 'current_year', 'description': 'The year when the notfication is triggered.'},
{'name': 'Datestamp', 'type': 'str', 'value': 'datestamp', 'description': 'The date (in date format) when the notification was triggered.'}, {'name': 'Current Month', 'type': 'int', 'value': 'current_month', 'description': 'The month when the notfication is triggered.', 'example': '1 to 12'},
{'name': 'Timestamp', 'type': 'str', 'value': 'timestamp', 'description': 'The time (in time format) when the notification was triggered.'}, {'name': 'Current Day', 'type': 'int', 'value': 'current_day', 'description': 'The day when the notfication is triggered.', 'example': '1 to 31'},
{'name': 'Unix Time', 'type': 'int', 'value': 'unixtime', 'description': 'The unix timestamp when the notification was triggered.'}, {'name': 'Current Hour', 'type': 'int', 'value': 'current_hour', 'description': 'The hour when the notfication is triggered.', 'example': '0 to 23'},
{'name': 'Current Minute', 'type': 'int', 'value': 'current_minute', 'description': 'The minute when the notfication is triggered.', 'example': '0 to 59'},
{'name': 'Current Second', 'type': 'int', 'value': 'current_second', 'description': 'The second when the notfication is triggered.', 'example': '0 to 59'},
{'name': 'Current Weekday', 'type': 'int', 'value': 'current_weekday', 'description': 'The ISO weekday when the notfication is triggered.', 'example': '1 (Mon) to 7 (Sun)'},
{'name': 'Current Week', 'type': 'int', 'value': 'current_week', 'description': 'The ISO week number when the notfication is triggered.', 'example': '1 to 52'},
{'name': 'Datestamp', 'type': 'str', 'value': 'datestamp', 'description': 'The date (in date format) when the notification is triggered.'},
{'name': 'Timestamp', 'type': 'str', 'value': 'timestamp', 'description': 'The time (in time format) when the notification is triggered.'},
{'name': 'Unix Time', 'type': 'int', 'value': 'unixtime', 'description': 'The unix timestamp when the notification is triggered.'},
] ]
}, },
{ {
@@ -396,7 +403,7 @@ NOTIFICATION_PARAMETERS = [
{ {
'category': 'Source Metadata Details', 'category': 'Source Metadata Details',
'parameters': [ 'parameters': [
{'name': 'Media Type', 'type': 'str', 'value': 'media_type', 'description': 'The type of media.', 'example': 'movie, show, season, episode, artist, album, track'}, {'name': 'Media Type', 'type': 'str', 'value': 'media_type', 'description': 'The type of media.', 'example': 'movie, show, season, episode, artist, album, track, clip'},
{'name': 'Title', 'type': 'str', 'value': 'title', 'description': 'The full title of the item.'}, {'name': 'Title', 'type': 'str', 'value': 'title', 'description': 'The full title of the item.'},
{'name': 'Library Name', 'type': 'str', 'value': 'library_name', 'description': 'The library name of the item.'}, {'name': 'Library Name', 'type': 'str', 'value': 'library_name', 'description': 'The library name of the item.'},
{'name': 'Show Name', 'type': 'str', 'value': 'show_name', 'description': 'The title of the TV series.'}, {'name': 'Show Name', 'type': 'str', 'value': 'show_name', 'description': 'The title of the TV series.'},
@@ -527,7 +534,14 @@ NEWSLETTER_PARAMETERS = [
{'name': 'Server Name', 'type': 'str', 'value': 'server_name', 'description': 'The name of your Plex Server.'}, {'name': 'Server Name', 'type': 'str', 'value': 'server_name', 'description': 'The name of your Plex Server.'},
{'name': 'Start Date', 'type': 'str', 'value': 'start_date', 'description': 'The start date of the newsletter.'}, {'name': 'Start Date', 'type': 'str', 'value': 'start_date', 'description': 'The start date of the newsletter.'},
{'name': 'End Date', 'type': 'str', 'value': 'end_date', 'description': 'The end date of the newsletter.'}, {'name': 'End Date', 'type': 'str', 'value': 'end_date', 'description': 'The end date of the newsletter.'},
{'name': 'Week Number', 'type': 'int', 'value': 'week_number', 'description': 'The week number of the year.'}, {'name': 'Current Year', 'type': 'int', 'value': 'current_year', 'description': 'The year of the start date of the newsletter.'},
{'name': 'Current Month', 'type': 'int', 'value': 'current_month', 'description': 'The month of the start date of the newsletter.', 'example': '1 to 12'},
{'name': 'Current Day', 'type': 'int', 'value': 'current_day', 'description': 'The day of the start date of the newsletter.', 'example': '1 to 31'},
{'name': 'Current Hour', 'type': 'int', 'value': 'current_hour', 'description': 'The hour of the start date of the newsletter.', 'example': '0 to 23'},
{'name': 'Current Minute', 'type': 'int', 'value': 'current_minute', 'description': 'The minute of the start date of the newsletter.', 'example': '0 to 59'},
{'name': 'Current Second', 'type': 'int', 'value': 'current_second', 'description': 'The second of the start date of the newsletter.', 'example': '0 to 59'},
{'name': 'Current Weekday', 'type': 'int', 'value': 'current_weekday', 'description': 'The ISO weekday of the start date of the newsletter.', 'example': '1 (Mon) to 7 (Sun)'},
{'name': 'Current Week', 'type': 'int', 'value': 'current_week', 'description': 'The ISO week number of the start date of the newsletter.', 'example': '1 to 52'},
{'name': 'Newsletter Time Frame', 'type': 'int', 'value': 'newsletter_time_frame', 'description': 'The time frame included in the newsletter.'}, {'name': 'Newsletter Time Frame', 'type': 'int', 'value': 'newsletter_time_frame', 'description': 'The time frame included in the newsletter.'},
{'name': 'Newsletter Time Frame Units', 'type': 'str', 'value': 'newsletter_time_frame_units', 'description': 'The time frame units included in the newsletter.'}, {'name': 'Newsletter Time Frame Units', 'type': 'str', 'value': 'newsletter_time_frame_units', 'description': 'The time frame units included in the newsletter.'},
{'name': 'Newsletter URL', 'type': 'str', 'value': 'newsletter_url', 'description': 'The self-hosted URL to the newsletter.'}, {'name': 'Newsletter URL', 'type': 'str', 'value': 'newsletter_url', 'description': 'The self-hosted URL to the newsletter.'},

View File

@@ -555,6 +555,14 @@ class Newsletter(object):
'server_name': plexpy.CONFIG.PMS_NAME, 'server_name': plexpy.CONFIG.PMS_NAME,
'start_date': self.start_date.format(date_format), 'start_date': self.start_date.format(date_format),
'end_date': self.end_date.format(date_format), 'end_date': self.end_date.format(date_format),
'current_year': self.start_date.year,
'current_month': self.start_date.month,
'current_day': self.start_date.day,
'current_hour': self.start_date.hour,
'current_minute': self.start_date.minute,
'current_second': self.start_date.second,
'current_weekday': self.start_date.isocalendar()[2],
'current_week': self.start_date.isocalendar()[1],
'week_number': self.start_date.isocalendar()[1], 'week_number': self.start_date.isocalendar()[1],
'newsletter_time_frame': self.config['time_frame'], 'newsletter_time_frame': self.config['time_frame'],
'newsletter_time_frame_units': self.config['time_frame_units'], 'newsletter_time_frame_units': self.config['time_frame_units'],

View File

@@ -701,6 +701,9 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
child_count = 1 child_count = 1
grandchild_count = 1 grandchild_count = 1
now = arrow.now()
now_iso = now.isocalendar()
available_params = { available_params = {
# Global paramaters # Global paramaters
'tautulli_version': common.RELEASE, 'tautulli_version': common.RELEASE,
@@ -715,9 +718,17 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
'server_platform': plexpy.CONFIG.PMS_PLATFORM, 'server_platform': plexpy.CONFIG.PMS_PLATFORM,
'server_version': plexpy.CONFIG.PMS_VERSION, 'server_version': plexpy.CONFIG.PMS_VERSION,
'action': notify_action.split('on_')[-1], 'action': notify_action.split('on_')[-1],
'week_number': arrow.now().isocalendar()[1], 'current_year': now.year,
'datestamp': arrow.now().format(date_format), 'current_month': now.month,
'timestamp': arrow.now().format(time_format), 'current_day': now.day,
'current_hour': now.hour,
'current_minute': now.minute,
'current_second': now.second,
'current_weekday': now_iso[2],
'current_week': now_iso[1],
'week_number': now_iso[1], # Keep for backwards compatibility
'datestamp': now.format(date_format),
'timestamp': now.format(time_format),
'unixtime': int(time.time()), 'unixtime': int(time.time()),
# Stream parameters # Stream parameters
'streams': stream_count, 'streams': stream_count,
@@ -909,6 +920,9 @@ def build_server_notify_params(notify_action=None, **kwargs):
pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {})) pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {}))
plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {})) plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {}))
now = arrow.now()
now_iso = now.isocalendar()
available_params = { available_params = {
# Global paramaters # Global paramaters
'tautulli_version': common.RELEASE, 'tautulli_version': common.RELEASE,
@@ -923,8 +937,17 @@ def build_server_notify_params(notify_action=None, **kwargs):
'server_version': plexpy.CONFIG.PMS_VERSION, 'server_version': plexpy.CONFIG.PMS_VERSION,
'server_machine_id': plexpy.CONFIG.PMS_IDENTIFIER, 'server_machine_id': plexpy.CONFIG.PMS_IDENTIFIER,
'action': notify_action.split('on_')[-1], 'action': notify_action.split('on_')[-1],
'datestamp': arrow.now().format(date_format), 'current_year': now.year,
'timestamp': arrow.now().format(time_format), 'current_month': now.month,
'current_day': now.day,
'current_hour': now.hour,
'current_minute': now.minute,
'current_second': now.second,
'current_weekday': now_iso[2],
'current_week': now_iso[1],
'week_number': now_iso[1], # Keep for backwards compatibility
'datestamp': now.format(date_format),
'timestamp': now.format(time_format),
'unixtime': int(time.time()), 'unixtime': int(time.time()),
# Plex Media Server update parameters # Plex Media Server update parameters
'update_version': pms_download_info['version'], 'update_version': pms_download_info['version'],

View File

@@ -590,6 +590,8 @@ class PmsConnect(object):
metadata_xml = self.get_metadata(str(rating_key), output_format='xml') metadata_xml = self.get_metadata(str(rating_key), output_format='xml')
elif sync_id: elif sync_id:
metadata_xml = self.get_sync_item(str(sync_id), output_format='xml') metadata_xml = self.get_sync_item(str(sync_id), output_format='xml')
else:
return metadata
try: try:
xml_head = metadata_xml.getElementsByTagName('MediaContainer') xml_head = metadata_xml.getElementsByTagName('MediaContainer')
@@ -1051,7 +1053,7 @@ class PmsConnect(object):
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'), 'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'), 'art': helpers.get_xml_attr(metadata_main, 'art'),
'banner': photo_album_details['banner'], 'banner': photo_album_details.get('banner', ''),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'), 'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'), 'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'), 'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
@@ -1060,10 +1062,10 @@ class PmsConnect(object):
'directors': directors, 'directors': directors,
'writers': writers, 'writers': writers,
'actors': actors, 'actors': actors,
'genres': photo_album_details['genres'], 'genres': photo_album_details.get('genres', ''),
'labels': photo_album_details['labels'], 'labels': photo_album_details.get('labels', ''),
'collections': photo_album_details['collections'], 'collections': photo_album_details.get('collections', ''),
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'), 'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle') or library_name,
helpers.get_xml_attr(metadata_main, 'title')), helpers.get_xml_attr(metadata_main, 'title')),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@@ -1160,7 +1162,7 @@ class PmsConnect(object):
} }
else: else:
return {} return metadata
if metadata and media_info: if metadata and media_info:
medias = [] medias = []
@@ -1264,7 +1266,7 @@ class PmsConnect(object):
return metadata return metadata
else: else:
return {} return metadata
def get_metadata_children_details(self, rating_key='', get_children=False): def get_metadata_children_details(self, rating_key='', get_children=False):
""" """

View File

@@ -1,2 +1,2 @@
PLEXPY_BRANCH = "master" PLEXPY_BRANCH = "master"
PLEXPY_RELEASE_VERSION = "v2.1.12" PLEXPY_RELEASE_VERSION = "v2.1.13"

View File

@@ -5845,3 +5845,8 @@ class WebInterface(object):
logger.error(u"Failed to retrieve newsletter: Missing newsletter_id parameter.") logger.error(u"Failed to retrieve newsletter: Missing newsletter_id parameter.")
return "Failed to retrieve newsletter: missing newsletter_id parameter" return "Failed to retrieve newsletter: missing newsletter_id parameter"
@cherrypy.expose
@requireAuth()
def support(self, query='', **kwargs):
return serve_template(templatename="support.html", title="Support")