A bunch of UI updates

This commit is contained in:
JonnyWong16 2016-04-23 00:11:30 -07:00
parent 11aa7d0140
commit d8ad9adabd
14 changed files with 425 additions and 176 deletions

View file

@ -14,7 +14,7 @@ from plexpy.helpers import anon_url
<meta name="author" content="">
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
<link href="${http_root}css/plexpy.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,800" rel="stylesheet" type="text/css">
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
${next.headIncludes()}
@ -176,9 +176,9 @@ from plexpy.helpers import anon_url
</form>
</li>
% if title == "Home":
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
% else:
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
% endif
% if title == "Libraries" or title == "Library" or title == "Info":
<li class="active"><a href="libraries">Libraries</a></li>
@ -186,9 +186,9 @@ from plexpy.helpers import anon_url
<li><a href="libraries">Libraries</a></li>
% endif
% if title == "Users" or title == "User":
<li class="active"><a href="users">Users</a></li>
<li class="active"><a href="users">Users</a></li>
% else:
<li><a href="users">Users</a></li>
<li><a href="users">Users</a></li>
% endif
% if title == "History":
<li class="active"><a href="history">History</a></li>
@ -196,25 +196,32 @@ from plexpy.helpers import anon_url
<li><a href="history">History</a></li>
% endif
% if title == "Graphs":
<li class="active"><a href="graphs">Graphs</a></li>
<li class="active"><a href="graphs">Graphs</a></li>
% else:
<li><a href="graphs">Graphs</a></li>
<li><a href="graphs">Graphs</a></li>
% endif
% if title == "Synced Items":
<li class="active"><a href="sync">Synced Items</a></li>
<li class="active"><a href="sync">Synced Items</a></li>
% else:
<li><a href="sync">Synced Items</a></li>
% endif
% if title == "Log":
<li class="active"><a href="logs">Logs</a></li>
% else:
<li><a href="logs">Logs</a></li>
<li><a href="sync">Synced Items</a></li>
% endif
% if title == "Settings":
<li class="active"><a href="settings">Settings</a></li>
<li class="dropdown active">
% else:
<li><a href="settings">Settings</a></li>
<li class="dropdown">
% endif
<a href="settings" class="dropdown-toggle disabled" aria-haspopup="true" data-toggle="dropdown" data-hover="dropdown"><i class="fa fa-lg fa-cogs"></i> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="logs"><i class="fa fa-list-alt"></i> View Logs</a></li>
<li role="separator" class="divider"></li>
% if plexpy.CONFIG.CHECK_GITHUB:
<li><a href="#" id="nav-update"><i class="fa fa-arrow-circle-up"></i> Check for Updates</a></li>
% endif
<li><a href="#" id="nav-restart"><i class="fa fa-refresh"></i> Restart</a></li>
<li><a href="#" id="nav-shutdown"><i class="fa fa-power-off"></i> Shutdown</a></li>
<li><a href="${http_root}auth/login"><i class="fa fa-sign-out"></i> Logout</a></li>
</ul>
</li>
</ul>
</div>
</div>
@ -239,6 +246,25 @@ ${next.headerIncludes()}
if (!getCookie('updateDismiss')) {
$('#updatebar').show();
}
$("#nav-shutdown").click(function () {
var r = confirm("Are you sure you want to shutdown PlexPy?");
if (r == true) {
window.location.href = "shutdown";
}
});
$("#nav-restart").click(function () {
window.location.href = "restart";
});
$("#nav-update").first().one("click", function () {
// Allow the update bar to show again if previously dismissed.
setCookie('updateDismiss', 'true', 0);
$(this).html('<i class="fa fa-spin fa-refresh"></i> Checking');
window.location.href = "checkGithub";
});
</script>
<script>
$('#search_form').submit(function (e) {
@ -263,8 +289,8 @@ ${next.headerIncludes()}
});
</script>
<script>
// Work around for iOS web app links opening in Safari
$(document).ready(function () {
// Work around for iOS web app links opening in Safari
if (("standalone" in window.navigator) && window.navigator.standalone) {
// For iOS Apps
$('a').on('click', function (e) {
@ -275,6 +301,17 @@ ${next.headerIncludes()}
}
});
}
// hack alert: if we don't have a touchscreen, and we are already hovering the mouse, then click should link instead of toggle
if ((navigator.maxTouchPoints || 0) < 2) {
$('.dropdown-toggle').on('click', function () {
var $this = $(this);
if ($this.attr('aria-expanded') === 'true') {
window.location.href = $this.attr('href');
}
});
}
});
</script>
${next.javascriptIncludes()}

View file

@ -1,5 +1,5 @@
body {
font-family: 'Open Sans', sans-serif;
font-family: 'Open Sans', Arial, sans-serif;
color: #fff;
margin-top: 50px;
overflow: hidden;
@ -9,7 +9,7 @@ a {
}
a:hover,
a:focus {
color: #f9aa03;
color: #e9a049;
text-decoration: none;
outline: none;
}
@ -89,7 +89,7 @@ img {
.nav > li.active > a,
.nav > li.active > a:hover,
.nav > li.active > a:focus {
color: #f9aa03;
color: #f9be03;
background-color: #282828;
}
.navbar-toggle {
@ -99,6 +99,36 @@ img {
.navbar-toggle:focus {
background-color: #2f2f2f;
}
@media screen and (min-width: 768px) {
.dropdown:hover > .dropdown-menu {
display: block;
}
}
.dropdown-menu {
background-color: #282828;
}
.dropdown-menu .divider {
background-color: #777;
}
.dropdown-menu > li > a {
color: #999;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
color: #fff;
background-color: #2f2f2f;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
color: #fff;
background-color: #2f2f2f;
}
.dropdown-menu > .disabled > a,
.dropdown-menu > .disabled > a:hover,
.dropdown-menu > .disabled > a:focus {
color: #999;
}
.icon-bar {
background-color: #999;
}
@ -109,7 +139,13 @@ img {
color: #eee;
}
.padded-header h3 {
font-size: 20px;
font-size: 16px;
font-weight: bold;
text-transform: uppercase;
}
.padded-header h3 small {
font-size: 13px;
text-transform: none;
}
.btn {
outline:0px !important;
@ -182,9 +218,9 @@ fieldset[disabled] .btn-dark.active {
background-color: #3B3B3B;
}
.btn-bright {
color: #fff;
background-color: #eb8600;
border-color: transparent;
color: #fff;
background-color: #cc7b19;
box-shadow: inset 0 1px 0 #e7993b;
}
.btn-bright:focus,
.btn-bright.focus {
@ -193,14 +229,15 @@ fieldset[disabled] .btn-dark.active {
}
.btn-bright:hover {
color: #fff;
background-color: #E69400;
border-color: #f9aa03;
background-color: #e59029;
box-shadow: inset 0 1px 0 #ebac60;
}
.btn-bright:active,
.btn-bright.active,
.open > .dropdown-toggle.btn-bright {
color: #fff;
background-color: #eb8600;
background-color: #cc7b19;
box-shadow: inset 0 1px 0 #e7993b;
}
.btn-bright:active:hover,
.btn-bright.active:hover,
@ -212,7 +249,8 @@ fieldset[disabled] .btn-dark.active {
.btn-bright.active.focus,
.open > .dropdown-toggle.btn-bright.focus {
color: #fff;
background-color: #eb8600;
background-color: #cc7b19;
box-shadow: inset 0 1px 0 #e7993b;
}
.btn-bright:active,
.btn-bright.active,
@ -237,12 +275,13 @@ fieldset[disabled] .btn-bright:active,
.btn-bright.disabled.active,
.btn-bright[disabled].active,
fieldset[disabled] .btn-bright.active {
background-color: #c9302c;
border-color: #ac2925;
background-color: #cc7b19;
border-color: #b56d16;
}
.btn-bright .badge {
color: #fff;
background-color: #eb8600;
background-color: #cc7b19;
box-shadow: inset 0 1px 0 #e7993b;
}
.btn-danger.btn-edit {
color: #d7d7d7;
@ -377,7 +416,7 @@ textarea.form-control:focus {
.pagination > li > span:hover,
.pagination > li > a:focus,
.pagination > li > span:focus {
background-color: #F9AA03;
background-color: #cc7b19;
border: 1px solid #444444;
}
.pagination > .active > a,
@ -389,7 +428,7 @@ textarea.form-control:focus {
z-index: 2;
color: #fff;
cursor: default;
background-color: #F9AA03;
background-color: #cc7b19;
border-color: #444444;
}
.pagination > .disabled > span,
@ -407,7 +446,7 @@ textarea.form-control:focus {
.nav-pills > li.active > a:hover,
.nav-pills > li.active > a:focus {
color: #fff;
background-color: #af6c17;
background-color: #cc7b19;
}
.nav-pills > li > a {
border-radius: 3px;
@ -871,16 +910,16 @@ a .dashboard-activity-metadata-user-thumb:hover {
color: #999;
}
.dashboard-activity-metadata-user a:hover {
color: #F9AA03;
color: #e9a049;
}
.dashboard-activity-metadata-title a:hover {
color: #F9AA03;
color: #e9a049;
}
.dashboard-activity-metadata-progress-wrapper {
margin-bottom: 20px;
font-size: 12px;
font-weight: bold;
color: #F9AA03;
color: #e9a049;
}
.dashboard-recent-media-row {
width: 100%;
@ -957,6 +996,7 @@ a:hover .dashboard-recent-media-cover {
.dashboard-recent-media-overlay-text {
color: #aaa;
font-size: 12px;
font-weight: bold;
float: left;
position: absolute;
left: 8px;
@ -974,9 +1014,9 @@ a:hover .dashboard-recent-media-cover {
overflow: hidden;
position: relative;
font-size: 13px;
font-weight: bold;
margin: 0;
line-height: 15px;
font-weight: normal;
width: 150px;
white-space: nowrap;
text-align: left;
@ -985,13 +1025,11 @@ a:hover .dashboard-recent-media-cover {
.dashboard-recent-media-metacontainer h3.text-muted {
color: #777;
}
.dashboard-recent-media-metacontainer .text-muted {
padding: 5px 3px 0 3px;
text-overflow: ellipsis;
overflow: hidden;
position: relative;
white-space: nowrap;
text-align: left;
.dashboard-recent-media-metacontainer h3.text-muted a {
color: #777;
}
.dashboard-recent-media-metacontainer h3.text-muted a:hover {
color: #e9a049;
}
.art-face {
background-repeat: no-repeat;
@ -1057,7 +1095,7 @@ a:hover .dashboard-recent-media-cover {
color: #999;
}
.summary-navbar-list .breadcrumb a:hover {
color: #F9AA03;
color: #f9be03;
}
.summary-content-title-wrapper {
height: 150px;
@ -1071,7 +1109,7 @@ a:hover .dashboard-recent-media-cover {
.summary-content-title h1 {
margin-top: 0;
margin-bottom: 10px;
color: #F9AA03;
color: #f9be03;
font-size: 28px;
line-height: 40px;
float: left;
@ -1082,11 +1120,10 @@ a:hover .dashboard-recent-media-cover {
width: 100%;
}
.summary-content-title h1 a {
color: #F9AA03;
color: #f9be03;
}
.summary-content-title h1 a:hover {
color: #F9AA03;
text-decoration: underline;
color: #fff;
}
.summary-content-title h2 {
margin-top: 0;
@ -1335,7 +1372,7 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
.star-rating .star-icon {
width: auto;
margin-left: 2px;
color: #F9AA03;
color: #f9be03;
}
.star-rating .star-icon-o {
width: auto;
@ -1438,6 +1475,7 @@ a:hover .item-children-poster {
.item-children-overlay-text {
color: #aaa;
font-size: 12px;
font-weight: bold;
float: left;
position: absolute;
left: 8px;
@ -1465,9 +1503,9 @@ a:hover .item-children-poster {
overflow: hidden;
position: relative;
font-size: 13px;
font-weight: bold;
margin: 0;
line-height: 15px;
font-weight: normal;
white-space: nowrap;
text-align: left;
clear: both;
@ -1475,6 +1513,12 @@ a:hover .item-children-poster {
.item-children-instance-text-wrapper h3.text-muted {
color: #777;
}
.item-children-instance-text-wrapper h3.text-muted a {
color: #777;
}
.item-children-instance-text-wrapper h3.text-muted a:hover {
color: #e9a049;
}
.item-children-list-item-odd {
border-top: 0px solid #343434;
border-bottom: 0px solid #343434;
@ -1519,7 +1563,7 @@ a:hover .item-children-poster {
margin-right: 20px;
}
#new_title h3 {
color: #F9AA03;
color: #f9be03;
font-size: 14px;
line-height: 1.42857143;
font-weight: bold;
@ -1582,10 +1626,15 @@ a:hover .item-children-poster {
top: 15px;
left: -5px;
}
.user-info-nav > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus {
color: #F9AA03;
.user-info-nav > .active > a {
color: #cc7b19;
}
.nav-tabs > .active > a:hover,
.nav-tabs > .active > a:focus {
color: #e9a049;
}
.user-info-nav a:hover {
color: #e9a049;
text-decoration: none;
}
.user-info-nav ul {
@ -1640,7 +1689,7 @@ a:hover .item-children-poster {
.user-overview-stats-instance h3 {
font-size: 30px;
font-weight: bold;
color: #F9AA03;
color: #f9be03;
line-height: 22px;
position: relative;
top: 5px;
@ -1692,8 +1741,8 @@ a:hover .item-children-poster {
text-overflow: ellipsis;
overflow: hidden;
position: relative;
font-size: 13px;
line-height: 15px;
font-size: 14px;
line-height: 16px;
font-weight: normal;
width: 140px;
margin-left: 10px;
@ -1702,7 +1751,7 @@ a:hover .item-children-poster {
.user-player-instance-playcount h3 {
font-size: 30px;
font-weight: bold;
color: #F9AA03;
color: #f9be03;
line-height: 22px;
position: relative;
top: 5px;
@ -1784,8 +1833,8 @@ a:hover .item-children-poster {
text-overflow: ellipsis;
overflow: hidden;
position: relative;
font-size: 13px;
line-height: 15px;
font-size: 14px;
line-height: 16px;
font-weight: bold;
width: 100%;
padding: 0 0 0 20px;
@ -1810,7 +1859,7 @@ a:hover .item-children-poster {
.home-platforms-instance-playcount h3 {
font-size: 30px;
font-weight: bold;
color: #F9AA03;
color: #f9be03;
line-height: 22px;
position: relative;
top: 5px;
@ -1919,7 +1968,7 @@ a:hover .item-children-poster {
height: 60px;
}
.home-platforms-instance-list-number {
background-color: #eb8600;
background-color: #f9be03;
float: left;
position: absolute;
top: -10px;
@ -1976,7 +2025,7 @@ a:hover .item-children-poster {
.home-platforms-instance-list-playcount h3 {
font-size: 20px;
font-weight: bold;
color: #F9AA03;
color: #f9be03;
line-height: 22px;
position: relative;
margin: 0 5px 0 0;
@ -2071,10 +2120,10 @@ a:hover .item-children-poster {
transition: all 0.3s ease;
}
.home-platforms-instance-list-chevron i:hover {
color: #eb8600;
color: #f9be03;
}
.home-platforms-instance-list-chevron.active i.fa-chevron-down{
color: #eb8600;
color: #f9be03;
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
@ -2173,6 +2222,7 @@ a .home-platforms-instance-list-oval:hover,
}
.header-bar span {
font-size: 22px;
font-weight: bold;
line-height: 34px;
}
.button-bar {
@ -2200,6 +2250,7 @@ a .home-platforms-instance-list-oval:hover,
border-top: 1px solid #2d2d2d;
}
.nav-settings > li > a {
border-bottom: 1px solid #232323;
display: block;
padding: 15px 15px 15px 15px;
color: #999;
@ -2215,7 +2266,7 @@ a .home-platforms-instance-list-oval:hover,
.nav-settings > .active > a,
.nav-settings > .active > a:hover,
.nav-settings > .active > a:focus {
color: #eb8600;
color: #f9be03;
background-color: #2f2f2f;
}
.stacked-configs,
@ -2257,7 +2308,7 @@ a .home-platforms-instance-list-oval:hover,
color: #eee;
}
.stacked-configs > li > span > a.active {
color: #eb8600;
color: #f9be03;
}
.accordion {
width: 100%;
@ -2299,10 +2350,10 @@ a .home-platforms-instance-list-oval:hover,
background: #2f2f2f;
}
.accordion li.open .link {
color: #eb8600;
color: #f9be03;
}
.accordion li.open i {
color: #eb8600;
color: #f9be03;
}
.accordion li.open i.fa-chevron-down {
-webkit-transform: rotate(180deg);
@ -2330,7 +2381,7 @@ a .home-platforms-instance-list-oval:hover,
transition: all 0.25s ease;
}
.submenu a:hover {
background: #eb8600;
background: #f9be03;
color: #FFF;
}
.ajaxMsg {
@ -2532,7 +2583,7 @@ a .home-platforms-instance-list-oval:hover,
margin-right: 3px;
}
#updatebar a:hover {
color: #F9AA03;
color: #e9a049;
}
.body-container {
position: absolute;
@ -2593,13 +2644,13 @@ table.display tr.shown + tr .pagination > .active > a:hover {
table.display tr.shown + tr table[id^='history_child'] td:hover a,
table.display tr.shown + tr table[id^='media_info_child'] > tr > td:hover a,
table.display tr.shown + tr table[id^='media_info_child'] tr.shown + tr table[id^='media_info_child'] td:hover a {
color: #F9AA03;
color: #cc7b19;
}
table.display tr.shown + tr .pagination > .disabled > a {
color: #444444;
}
table.display tr.shown + tr .pagination > li > a:hover {
color: #23527c;
color: #e9a049;
}
table[id^='history_child'] {
margin-top: 0;
@ -2791,6 +2842,8 @@ a.no-highlight:hover {
#recently-added-row-scroller,
#recently-watched-row-scroller {
position: relative;
height: 265px;
margin-bottom: 25px;
}
@media (min-width: 768px) {

View file

@ -18,9 +18,9 @@ DOCUMENTATION :: END
% if data == '0':
<h3>Activity</h3>
% elif data == '1':
<h3>Activity <small>${data} stream</small></h3>
<h3>Activity &nbsp;&nbsp;<small>${data} stream</small></h3>
% else:
<h3>Activity <small>${data} streams</small></h3>
<h3>Activity &nbsp;&nbsp;<small>${data} streams</small></h3>
% endif
% else:
<h3>Activity</h3>

View file

@ -5,6 +5,8 @@
<%def name="body()">
<div class="container-fluid">
% for section in config['home_sections']:
% if section == 'current_activity':
<div class="row">
<div class="col-md-12">
<div class="padded-header" id="current-activity-header">
@ -16,11 +18,11 @@
</div>
</div>
</div>
% if config['home_stats_cards']:
% elif section == 'watch_stats':
<div class="row">
<div class="col-md-12">
<div class="padded-header">
<h3>Watch Statistics <small>Last ${config['home_stats_length']} days</small></h3>
<h3>Watch Statistics &nbsp;&nbsp;<small>Last ${config['home_stats_length']} days</small></h3>
</div>
<div id="home-stats" class="home-platforms">
<div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
@ -28,12 +30,11 @@
</div>
</div>
</div>
% endif
% if config['home_library_cards']:
% elif section == 'library_stats':
<div class="row">
<div class="col-md-12">
<div class="padded-header" id="library-statistics-header">
<h3>Library Statistics <small>${config['pms_name']}</small></h3>
<h3>Library Statistics &nbsp;&nbsp;<small>${config['pms_name']}</small></h3>
</div>
<div id="library-stats" class="library-platforms">
<div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Loading stats...</div>
@ -41,7 +42,7 @@
</div>
</div>
</div>
% endif
% elif section == 'recently_added':
<div class="row">
<div class="col-md-12">
<div class="padded-header">
@ -53,7 +54,10 @@
<a href="#" id="recently-added-page-right" class="paginate btn-gray disabled" data-id="-1"><i class="fa fa-lg fa-chevron-right"></i></a>
</li>
</ul>
<h3>Recently Added</h3>
<h3>Recently Added &nbsp;&nbsp;<small>
<a href="#" class="toggle-recently-added-type" data-type="movie">Movies</a> &nbsp;
<a href="#" class="toggle-recently-added-type" data-type="season">TV Shows</a> &nbsp;
<a href="#" class="toggle-recently-added-type" data-type="album">Music</a></small></h3>
</div>
<div id="recentlyAdded" style="margin-right: -15px;">
<div class="text-muted"><i class="fa fa-refresh fa-spin"></i> Looking for new items...</div>
@ -61,6 +65,8 @@
</div>
</div>
</div>
% endif
% endfor
</div>
</%def>
@ -186,6 +192,13 @@
$("#recently-added-page-right").removeClass("disabled");
}
});
$('.toggle-recently-added-type').click(function () {
var media_type = $(this).data('type');
var margin_right = $(this).hasClass('text-muted') ? '25px' : 0;
$('.dashboard-recent-media-instance li[data-type=' + media_type + ']').animate({ width: 'toggle', marginRight: margin_right }, 1000);
$(this).toggleClass('text-muted').blur();
});
</script>
</%def>

View file

@ -119,7 +119,7 @@ DOCUMENTATION :: END
</div>
</div>
% elif data['media_type'] == 'artist' or data['media_type'] == 'album' or data['media_type'] == 'track':
<div class="summary-poster-face-track" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=500&fallback=poster);">
<div class="summary-poster-face-track" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=500&fallback=cover);">
<div class="summary-poster-face-overlay">
<span></span>
</div>

View file

@ -42,32 +42,40 @@ DOCUMENTATION :: END
% if item['media_type'] == 'episode':
% if item['parent_thumb']:
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['parent_thumb']}&width=300&height=450&fallback=poster);">
% else:
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['grandparent_thumb']}&width=300&height=450&fallback=poster);">
% endif
% elif item['media_type'] == 'movie':
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
% endif
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
$('#added_at-${item['rating_key']}').text('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
</div>
</div>
% else:
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['grandparent_thumb']}&width=300&height=450&fallback=poster);">
% endif
% elif item['media_type'] == 'movie':
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
% endif
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
$('#added_at-${item['rating_key']}').text('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode':
<h3 title="${item['grandparent_title']}">${item['grandparent_title']}</h3>
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">S${item['parent_media_index']} &middot; E${item['media_index']}</h3>
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
</div>
</div>
</div>
</a>
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode':
<h3 title="${item['grandparent_title']}">
<a href="info?rating_key=${item['grandparent_rating_key']}">${item['grandparent_title']}</a>
</h3>
<h3 title="${item['title']}">
<a href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="info?rating_key=${item['parent_rating_key']}">S${item['parent_media_index']}</a> &middot; <a href="info?rating_key=${item['rating_key']}">E${item['media_index']}</a>
</h3>
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">
<a href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
</div>
% elif item['media_type'] == 'album':
<a href="info?rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-cover">
@ -82,8 +90,12 @@ DOCUMENTATION :: END
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['parent_title']}">${item['parent_title']}</h3>
<h3 class="text-muted">${item['title']}</h3>
<h3 title="${item['parent_title']}">
<a href="info?rating_key=${item['parent_rating_key']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
</div>
</a>
% endif

View file

@ -9,6 +9,8 @@
<meta name="author" content="">
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
<link href="${http_root}css/plexpy.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,800" rel="stylesheet" type="text/css">
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="${http_root}images/favicon.ico"/>
<link rel="shortcut icon" href="${http_root}images/favicon.ico">
</head>
@ -40,7 +42,7 @@
<input type="password" id="password" name="password" class="form-control">
</div>
<div class="form-footer">
<button type="submit" class="btn btn-lg btn-bright login-button">Sign In</button>
<button type="submit" class="btn btn-bright login-button"><i class="fa fa-sign-in"></i>&nbsp; Sign In</button>
<div class="remember-group">
<label class="control-label">
<input type="checkbox" id="remember_me" name="remember_me" title="for 30 days" value=1 checked="checked" /> Remember me

View file

@ -36,11 +36,11 @@ DOCUMENTATION :: END
<ul class="dashboard-recent-media list-unstyled">
% for item in data:
<div class="dashboard-recent-media-instance">
<li>
% if item['media_type'] == 'season' or item['media_type'] == 'movie':
<a href="info?rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
<li data-type="${item['media_type']}">
% if item['media_type'] == 'movie':
<a href="info?rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -50,16 +50,35 @@ DOCUMENTATION :: END
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'season':
<h3 title="${item['parent_title']}">${item['parent_title']}</h3>
<h3 class="text-muted">${item['title']}</h3>
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
</div>
</a>
</a>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['title']}">
<a href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
</div>
% elif item['media_type'] == 'season':
<a href="info?rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['parent_thumb']}&width=300&height=450&fallback=poster);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
$('#added_at-${item['rating_key']}').text('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
</div>
</div>
</div>
</div>
</a>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['parent_title']}">
<a href="info?rating_key=${item['parent_rating_key']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
</div>
% elif item['media_type'] == 'album':
<a href="info?rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-cover">
@ -73,11 +92,15 @@ DOCUMENTATION :: END
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['parent_title']}">${item['parent_title']}</h3>
<h3 class="text-muted">${item['title']}</h3>
</div>
</a>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['parent_title']}">
<a href="info?rating_key=${item['parent_rating_key']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="info?rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
</div>
% endif
</li>
</div>

View file

@ -20,7 +20,7 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<div class="col-md-12">
<div class='card-back-full'>
<div class="header-bar">
<span><i class="fa fa-cog"></i> Settings</span>
<span><i class="fa fa-cogs"></i> Settings</span>
</div>
<div class="button-bar">
% if config['check_github']:
@ -131,10 +131,15 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<td>Gitter Chat:</td>
<td><a class="no-highlight" href="${anon_url('https://gitter.im/drzoidberg33/plexpy')}" target="_blank">https://gitter.im/drzoidberg33/plexpy</a></td>
</tr>
<tr>
<td>Donations:</td>
<td><a class="no-highlight" href="${anon_url('https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DG783BMSCU3V4')}" target="_blank">Paypal</a> |
<a class="no-highlight" href="${anon_url('http://swiftpanda16.tip.me/')}" target="_blank">Bitcoin</a></td>
</tr>
</tbody>
</table>
<div class="padded-header">
<h3>PlexPy Scheduler</h3>
<h3>PlexPy Scheduled Tasks</h3>
</div>
<div id="plexpy-scheduler-table">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading scheduler table...</div>
@ -228,7 +233,49 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-2">
<div class="padded-header">
<h3>Homepage</h3>
</div>
<label for="sortable_home_stats_cards">Sections</label>
<p class="help-block">
Select the sections to show on the homepage.<br>
Drag the items below to reorder your homepage content.
</p>
<div class="row">
<div class="col-md-6">
<ul class="list-unstyled" id="sortable_home_sections" data-parsley-trigger="change">
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hsec-current_activity" name="hsec-current_activity" value="current_activity"> Current Activity
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hsec-watch_stats" name="hsec-watch_stats" value="watch_stats"> Watch Statistics
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hsec-library_stats" name="hsec-library_stats" value="library_stats"> Library Statistics
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hsec-recently_added" name="hsec-recently_added" value="recently_added"> Recently Added
</label>
</li>
</ul>
<input type="text" id="home_sections" name="home_sections" style="display: none;"/>
</div>
</div>
<div class="padded-header">
<h3>Watch Statistics</h3>
</div>
@ -236,24 +283,12 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<div class="form-group">
<label for="sortable_home_stats_cards">Cards</label>
<p class="help-block">
Select the cards to show in the watch statistics on the home page. Select none to disable.<br>
Select the cards to show in the watch statistics on the home page.
Drag the items below to reorder your homepage content.
</p>
<div class="row">
<div class="col-md-6">
<ul class="list-unstyled" id="sortable_home_stats_cards" data-parsley-trigger="change">
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hscard-top_tv" name="hscard-top_tv" value="top_tv"> Most Watched TV
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hscard-popular_tv" name="hscard-popular_tv" value="popular_tv"> Most Popular TV
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
@ -266,6 +301,18 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<input type="checkbox" id="hscard-popular_movies" name="hscard-popular_movies" value="popular_movies"> Most Popular Movie
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hscard-top_tv" name="hscard-top_tv" value="top_tv"> Most Watched TV
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
<input type="checkbox" id="hscard-popular_tv" name="hscard-popular_tv" value="popular_tv"> Most Popular TV
</label>
</li>
<li class="card card-sortable">
<div class="card-handle"><i class="fa fa-bars"></i></div>
<label>
@ -341,17 +388,17 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
<div class="form-group">
<label for="home_library_cards">Cards</label>
<p class="help-block">
Select the cards to show in the library statistics on the home page. Select none to disable.<br>
Select the cards to show in the library statistics on the home page.
Drag the items below to reorder your homepage content.
</p>
<div class="row">
<div class="col-md-6">
<ul class="list-unstyled" id="sortable_home_library_cards" data-parsley-trigger="change">
</ul>
<ul class="list-unstyled" id="sortable_home_library_cards" data-parsley-trigger="change"></ul>
<input type="text" id="home_library_cards" name="home_library_cards" style="display: none;" />
</div>
</div>
</div>
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
@ -2002,15 +2049,11 @@ $(document).ready(function() {
$("#menu_link_update_check").click(function() {
// Allow the update bar to show again if previously dismissed.
setCookie('updateDismiss', 'true', 0);
$(this).html('<i class="fa fa-spin fa-refresh"></i> Checking</button>');
$(this).html('<i class="fa fa-spin fa-refresh"></i> Checking');
$(this).prop('disabled', true);
window.location.href = "checkGithub";
});
$("#modal_link_restart").click(function() {
window.location.href = "restart";
});
if ($("#api_enabled").is(":checked")) {
$("#apioptions").show();
} else {
@ -2301,6 +2344,31 @@ $(document).ready(function() {
var accordion_timeline = new Accordion($('#accordion-timeline'), false);
var accordion_scripts = new Accordion($('#accordion-scripts'), false);
// Sortable home_sections
function set_home_sections() {
var home_sections = [];
var hsecs = $('[id^=hsec-]').serializeArray();
$.each(hsecs, function(i, sec) {
home_sections.push(sec.value);
});
$('#home_sections').val(home_sections);
};
var sec_cards = ${config['home_sections'] | n};
sec_cards.reverse().forEach(function (item) {
$('#hsec-' + item).prop('checked', !$(this).prop('checked'))
$('#hsec-' + item).closest('li.card').prependTo('#sortable_home_sections');
});
Sortable.create(sortable_home_sections, {
animation: 250,
onSort: function(elem, ui) {
set_home_sections();
}
});
$('[id^=hsec-]').change(function() { set_home_sections(); });
set_home_sections()
// Sortable home_stats_cards
function set_home_stats_cards() {
@ -2328,7 +2396,6 @@ $(document).ready(function() {
$('[id^=hscard-]').change(function() { set_home_stats_cards(); });
set_home_stats_cards()
// Sortable home_library_cards
function set_home_library_cards() {
var home_library_cards = [];

View file

@ -45,17 +45,25 @@ DOCUMENTATION :: END
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode':
<h3 title="${item['grandparent_title']}">${item['grandparent_title']}</h3>
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">S${item['parent_media_index']} &middot; E${item['media_index']}</h3>
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
</div>
</a>
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode':
<h3 title="${item['grandparent_title']}">
<a href="info?rating_key=${item['grandparent_rating_key']}">${item['grandparent_title']}</a>
</h3>
<h3 title="${item['title']}">
<a href="info?source=history&rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="info?rating_key=${item['parent_rating_key']}">S${item['parent_media_index']}</a> &middot; <a href="info?source=history&rating_key=${item['rating_key']}">E${item['media_index']}</a>
</h3>
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">
<a href="info?source=history&rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
</div>
% elif item['media_type'] == 'track':
<a href="info?source=history&rating_key=${item['rating_key']}">
<div class="dashboard-recent-media-cover">
@ -69,12 +77,18 @@ DOCUMENTATION :: END
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['grandparent_title']}">${item['grandparent_title']}</h3>
<h3 title="${item['title']}">${item['title']}</h3>
<h3 class="text-muted">${item['parent_title']}</h3>
</div>
</a>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['grandparent_title']}">
<a href="info?rating_key=${item['grandparent_rating_key']}">${item['grandparent_title']}</a>
</h3>
<h3 title="${item['title']}">
<a href="info?source=history&rating_key=${item['rating_key']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="info?rating_key=${item['parent_rating_key']}">${item['parent_title']}</a></a>
</h3>
</div>
% endif
</li>
% endfor

View file

@ -132,11 +132,12 @@ _CONFIG_DEFINITIONS = {
'GROWL_ON_EXTUP': (int, 'Growl', 0),
'GROWL_ON_INTUP': (int, 'Growl', 0),
'GROWL_ON_PMSUPDATE': (int, 'Growl', 0),
'HOME_SECTIONS': (list, 'General', ['current_activity','watch_stats','library_stats','recently_added']),
'HOME_LIBRARY_CARDS': (list, 'General', ['first_run']),
'HOME_STATS_LENGTH': (int, 'General', 30),
'HOME_STATS_TYPE': (int, 'General', 0),
'HOME_STATS_COUNT': (int, 'General', 5),
'HOME_STATS_CARDS': (list, 'General', ['top_tv', 'popular_tv', 'top_movies', 'popular_movies', 'top_music', \
'HOME_STATS_CARDS': (list, 'General', ['top_movies', 'popular_movies', 'top_tv', 'popular_tv', 'top_music', \
'popular_music', 'last_watched', 'top_users', 'top_platforms', 'most_concurrent']),
'HTTPS_CREATE_CERT': (int, 'General', 1),
'HTTPS_CERT': (str, 'General', ''),
@ -605,3 +606,15 @@ class Config(object):
if self.CONFIG_VERSION == '3':
if self.HTTP_ROOT == '/': self.HTTP_ROOT = ''
self.CONFIG_VERSION = '4'
if self.CONFIG_VERSION == '4':
print not len(self.HOME_STATS_CARDS) and 'watch_stats' in self.HOME_SECTIONS
if not len(self.HOME_STATS_CARDS) and 'watch_stats' in self.HOME_SECTIONS:
home_sections = self.HOME_SECTIONS
home_sections.remove('watch_stats')
self.HOME_SECTIONS = home_sections
if not len(self.HOME_LIBRARY_CARDS) and 'library_stats' in self.HOME_SECTIONS:
home_sections = self.HOME_SECTIONS
home_sections.remove('library_stats')
self.HOME_SECTIONS = home_sections
self.CONFIG_VERSION = '4'

View file

@ -711,7 +711,8 @@ class Libraries(object):
try:
if str(section_id).isdigit():
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
query = 'SELECT session_history.id, session_history.media_type, ' \
'session_history.rating_key, session_history.parent_rating_key, session_history.grandparent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
@ -738,6 +739,8 @@ class Libraries(object):
recent_output = {'row_id': row['id'],
'media_type': row['media_type'],
'rating_key': row['rating_key'],
'parent_rating_key': row['parent_rating_key'],
'grandparent_rating_key': row['grandparent_rating_key'],
'title': row['title'],
'parent_title': row['parent_title'],
'grandparent_title': row['grandparent_title'],

View file

@ -439,7 +439,8 @@ class Users(object):
try:
if str(user_id).isdigit():
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
query = 'SELECT session_history.id, session_history.media_type, ' \
'session_history.rating_key, session_history.parent_rating_key, session_history.grandparent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
@ -466,6 +467,8 @@ class Users(object):
recent_output = {'row_id': row['id'],
'media_type': row['media_type'],
'rating_key': row['rating_key'],
'parent_rating_key': row['parent_rating_key'],
'grandparent_rating_key': row['grandparent_rating_key'],
'title': row['title'],
'parent_title': row['parent_title'],
'grandparent_title': row['grandparent_title'],

View file

@ -150,6 +150,7 @@ class WebInterface(object):
@require()
def home(self):
config = {
"home_sections": plexpy.CONFIG.HOME_SECTIONS,
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
"home_stats_cards": plexpy.CONFIG.HOME_STATS_CARDS,
"home_library_cards": plexpy.CONFIG.HOME_LIBRARY_CARDS,
@ -1290,6 +1291,7 @@ class WebInterface(object):
"notify_on_pmsupdate_subject_text": plexpy.CONFIG.NOTIFY_ON_PMSUPDATE_SUBJECT_TEXT,
"notify_on_pmsupdate_body_text": plexpy.CONFIG.NOTIFY_ON_PMSUPDATE_BODY_TEXT,
"notify_scripts_args_text": plexpy.CONFIG.NOTIFY_SCRIPTS_ARGS_TEXT,
"home_sections": json.dumps(plexpy.CONFIG.HOME_SECTIONS),
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
"home_stats_type": checked(plexpy.CONFIG.HOME_STATS_TYPE),
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
@ -1309,15 +1311,15 @@ class WebInterface(object):
checked_configs = [
"launch_browser", "enable_https", "https_create_cert", "api_enabled", "freeze_db", "check_github",
"grouping_global_history", "grouping_user_history", "grouping_charts", "pms_use_bif", "pms_ssl",
"grouping_global_history", "grouping_user_history", "grouping_charts", "group_history_tables",
"pms_use_bif", "pms_ssl", "pms_is_remote", "home_stats_type",
"movie_notify_enable", "tv_notify_enable", "music_notify_enable", "monitoring_use_websocket",
"tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start",
"tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop",
"tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause",
"refresh_libraries_on_startup", "refresh_users_on_startup",
"ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable",
"pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive", "notify_upload_posters",
"notify_recently_added", "notify_recently_added_grandparent",
"notify_consecutive", "notify_upload_posters", "notify_recently_added", "notify_recently_added_grandparent",
"monitor_pms_updates", "monitor_remote_access", "get_file_sizes", "log_blacklist", "http_hash_password"
]
for checked_config in checked_configs:
@ -1380,8 +1382,15 @@ class WebInterface(object):
kwargs.get('https_key') != plexpy.CONFIG.HTTPS_KEY:
https_changed = True
# Remove config with 'hsec-' prefix and change home_sections to list
if kwargs.get('home_sections'):
for k in kwargs.keys():
if k.startswith('hsec-'):
del kwargs[k]
kwargs['home_sections'] = kwargs['home_sections'].split(',')
# Remove config with 'hscard-' prefix and change home_stats_cards to list
if kwargs.get('home_stats_cards', ''):
if kwargs.get('home_stats_cards'):
for k in kwargs.keys():
if k.startswith('hscard-'):
del kwargs[k]
@ -1391,7 +1400,7 @@ class WebInterface(object):
kwargs['home_stats_cards'] = plexpy.CONFIG.HOME_STATS_CARDS
# Remove config with 'hlcard-' prefix and change home_library_cards to list
if kwargs.get('home_library_cards', ''):
if kwargs.get('home_library_cards'):
for k in kwargs.keys():
if k.startswith('hlcard-'):
del kwargs[k]