mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 21:21:15 -07:00
Initial implementation of login control
This commit is contained in:
parent
0aa2537d1e
commit
51a12099e4
24 changed files with 541 additions and 224 deletions
|
@ -12,14 +12,14 @@ from plexpy.helpers import anon_url
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
<link href="interfaces/default/css/bootstrap3/bootstrap.css" rel="stylesheet">
|
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
|
||||||
<link href="interfaces/default/css/plexpy.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" rel="stylesheet" type="text/css">
|
||||||
<link href="interfaces/default/css/font-awesome.min.css" rel="stylesheet">
|
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
|
||||||
${next.headIncludes()}
|
${next.headIncludes()}
|
||||||
|
|
||||||
<link rel="icon" type="image/x-icon" href="interfaces/default/images/favicon.ico"/>
|
<link rel="icon" type="image/x-icon" href="${http_root}images/favicon.ico"/>
|
||||||
<link rel="shortcut icon" href="interfaces/default/images/favicon.png">
|
<link rel="shortcut icon" href="${http_root}images/favicon.png">
|
||||||
|
|
||||||
<!-- Allow web app to be run in full-screen mode. -->
|
<!-- Allow web app to be run in full-screen mode. -->
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
@ -33,99 +33,99 @@ from plexpy.helpers import anon_url
|
||||||
<!-- ICONS -->
|
<!-- ICONS -->
|
||||||
<!-- IE10 icon -->
|
<!-- IE10 icon -->
|
||||||
<meta name="application-name" content="PlexPy" />
|
<meta name="application-name" content="PlexPy" />
|
||||||
<meta name="msapplication-config" content="interfaces/default/xml/IEconfig.xml"/>
|
<meta name="msapplication-config" content="${http_root}xml/IEconfig.xml"/>
|
||||||
<!-- Android >M39 icon -->
|
<!-- Android >M39 icon -->
|
||||||
<link rel="manifest" href="interfaces/default/json/Android-manifest.json">
|
<link rel="manifest" href="${http_root}json/Android-manifest.json">
|
||||||
<!-- iPad retina icon -->
|
<!-- iPad retina icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-76@2x.png" sizes="152x152" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-76@2x.png" sizes="152x152" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPad retina icon (iOS < 7) -->
|
<!-- iPad retina icon (iOS < 7) -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-72@2x.png" sizes="144x144" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-72@2x.png" sizes="144x144" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPad non-retina icon -->
|
<!-- iPad non-retina icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-76.png" sizes="76x76" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-76.png" sizes="76x76" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPad non-retina icon (iOS < 7) -->
|
<!-- iPad non-retina icon (iOS < 7) -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-72.png" sizes="72x72" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-72.png" sizes="72x72" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPhone 6 Plus icon -->
|
<!-- iPhone 6 Plus icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-60@2x.png" sizes="120x120" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-60@2x.png" sizes="120x120" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPhone retina icon (iOS < 7) -->
|
<!-- iPhone retina icon (iOS < 7) -->
|
||||||
<link href="interfaces/default/images/res/ios/icon@2x.png" sizes="114x114" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon@2x.png" sizes="114x114" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPhone non-retina icon (iOS < 7) -->
|
<!-- iPhone non-retina icon (iOS < 7) -->
|
||||||
<link href="interfaces/default/images/res/ios/icon.png" sizes="57x57" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon.png" sizes="57x57" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPhone / iPod Touch -->
|
<!-- iPhone / iPod Touch -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-60@3x.png" sizes="180x180" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-60@3x.png" sizes="180x180" rel="apple-touch-icon-precomposed">
|
||||||
<link href="interfaces/default/images/res/ios/icon-60.png" sizes="60x60" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-60.png" sizes="60x60" rel="apple-touch-icon-precomposed">
|
||||||
<!-- Spotlight Icon -->
|
<!-- Spotlight Icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-40.png" sizes="40x40" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-40.png" sizes="40x40" rel="apple-touch-icon-precomposed">
|
||||||
<link href="interfaces/default/images/res/ios/icon-40@2x.png" sizes="80x80" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-40@2x.png" sizes="80x80" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPhone Spotlight and Settings Icon -->
|
<!-- iPhone Spotlight and Settings Icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-small.png" sizes="29x29" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-small.png" sizes="29x29" rel="apple-touch-icon-precomposed">
|
||||||
<link href="interfaces/default/images/res/ios/icon-small@2x.png" sizes="58x58" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-small@2x.png" sizes="58x58" rel="apple-touch-icon-precomposed">
|
||||||
<!-- iPad Spotlight and Settings Icon -->
|
<!-- iPad Spotlight and Settings Icon -->
|
||||||
<link href="interfaces/default/images/res/ios/icon-50.png" sizes="50x50" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-50.png" sizes="50x50" rel="apple-touch-icon-precomposed">
|
||||||
<link href="interfaces/default/images/res/ios/icon-50@2x.png" sizes="100x100" rel="apple-touch-icon-precomposed">
|
<link href="${http_root}images/res/ios/icon-50@2x.png" sizes="100x100" rel="apple-touch-icon-precomposed">
|
||||||
|
|
||||||
<!-- STARTUP IMAGES -->
|
<!-- STARTUP IMAGES -->
|
||||||
<!-- iPad retina portrait startup image -->
|
<!-- iPad retina portrait startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-Portrait@2x~ipad.png"
|
<link href="${http_root}images/res/screen/ios/Default-Portrait@2x~ipad.png"
|
||||||
media="(device-width: 768px) and (device-height: 1024px)
|
media="(device-width: 768px) and (device-height: 1024px)
|
||||||
and (-webkit-device-pixel-ratio: 2)
|
and (-webkit-device-pixel-ratio: 2)
|
||||||
and (orientation: portrait)"
|
and (orientation: portrait)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPad retina landscape startup image -->
|
<!-- iPad retina landscape startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-Landscape@2x~ipad.png"
|
<link href="${http_root}images/res/screen/ios/Default-Landscape@2x~ipad.png"
|
||||||
media="(device-width: 768px) and (device-height: 1024px)
|
media="(device-width: 768px) and (device-height: 1024px)
|
||||||
and (-webkit-device-pixel-ratio: 2)
|
and (-webkit-device-pixel-ratio: 2)
|
||||||
and (orientation: landscape)"
|
and (orientation: landscape)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPad non-retina portrait startup image -->
|
<!-- iPad non-retina portrait startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-Portrait~ipad.png"
|
<link href="${http_root}images/res/screen/ios/Default-Portrait~ipad.png"
|
||||||
media="(device-width: 768px) and (device-height: 1024px)
|
media="(device-width: 768px) and (device-height: 1024px)
|
||||||
and (-webkit-device-pixel-ratio: 1)
|
and (-webkit-device-pixel-ratio: 1)
|
||||||
and (orientation: portrait)"
|
and (orientation: portrait)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPad non-retina landscape startup image -->
|
<!-- iPad non-retina landscape startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-Landscape~ipad.png"
|
<link href="${http_root}images/res/screen/ios/Default-Landscape~ipad.png"
|
||||||
media="(device-width: 768px) and (device-height: 1024px)
|
media="(device-width: 768px) and (device-height: 1024px)
|
||||||
and (-webkit-device-pixel-ratio: 1)
|
and (-webkit-device-pixel-ratio: 1)
|
||||||
and (orientation: landscape)"
|
and (orientation: landscape)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone 6 Plus portrait startup image -->
|
<!-- iPhone 6 Plus portrait startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-736h.png"
|
<link href="${http_root}images/res/screen/ios/Default-736h.png"
|
||||||
media="(device-width: 414px) and (device-height: 736px)
|
media="(device-width: 414px) and (device-height: 736px)
|
||||||
and (-webkit-device-pixel-ratio: 3)
|
and (-webkit-device-pixel-ratio: 3)
|
||||||
and (orientation: portrait)"
|
and (orientation: portrait)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone 6 Plus landscape startup image -->
|
<!-- iPhone 6 Plus landscape startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-Landscape-736h.png"
|
<link href="${http_root}images/res/screen/ios/Default-Landscape-736h.png"
|
||||||
media="(device-width: 414px) and (device-height: 736px)
|
media="(device-width: 414px) and (device-height: 736px)
|
||||||
and (-webkit-device-pixel-ratio: 3)
|
and (-webkit-device-pixel-ratio: 3)
|
||||||
and (orientation: landscape)"
|
and (orientation: landscape)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone 6 startup image -->
|
<!-- iPhone 6 startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-667h.png"
|
<link href="${http_root}images/res/screen/ios/Default-667h.png"
|
||||||
media="(device-width: 375px) and (device-height: 667px)
|
media="(device-width: 375px) and (device-height: 667px)
|
||||||
and (-webkit-device-pixel-ratio: 2)"
|
and (-webkit-device-pixel-ratio: 2)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone 5 startup image -->
|
<!-- iPhone 5 startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default-568h@2x~iphone5.jpg"
|
<link href="${http_root}images/res/screen/ios/Default-568h@2x~iphone5.jpg"
|
||||||
media="(device-width: 320px) and (device-height: 568px)
|
media="(device-width: 320px) and (device-height: 568px)
|
||||||
and (-webkit-device-pixel-ratio: 2)"
|
and (-webkit-device-pixel-ratio: 2)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone < 5 retina startup image -->
|
<!-- iPhone < 5 retina startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default@2x~iphone.png"
|
<link href="${http_root}images/res/screen/ios/Default@2x~iphone.png"
|
||||||
media="(device-width: 320px) and (device-height: 480px)
|
media="(device-width: 320px) and (device-height: 480px)
|
||||||
and (-webkit-device-pixel-ratio: 2)"
|
and (-webkit-device-pixel-ratio: 2)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
|
||||||
<!-- iPhone < 5 non-retina startup image -->
|
<!-- iPhone < 5 non-retina startup image -->
|
||||||
<link href="interfaces/default/images/res/screen/ios/Default~iphone.png"
|
<link href="${http_root}images/res/screen/ios/Default~iphone.png"
|
||||||
media="(device-width: 320px) and (device-height: 480px)
|
media="(device-width: 320px) and (device-height: 480px)
|
||||||
and (-webkit-device-pixel-ratio: 1)"
|
and (-webkit-device-pixel-ratio: 1)"
|
||||||
rel="apple-touch-startup-image">
|
rel="apple-touch-startup-image">
|
||||||
|
@ -158,7 +158,7 @@ from plexpy.helpers import anon_url
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="home">
|
<a class="navbar-brand" href="home">
|
||||||
<img alt="PlexPy" src="interfaces/default/images/logo-plexpy@2x.png" height="40">
|
<img alt="PlexPy" src="${http_root}images/logo-plexpy@2x.png" height="40">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
||||||
|
@ -226,9 +226,9 @@ ${next.headerIncludes()}
|
||||||
${next.body()}
|
${next.body()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="interfaces/default/js/jquery-2.1.4.min.js"></script>
|
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
|
||||||
<script src="interfaces/default/js/bootstrap3/bootstrap.min.js"></script>
|
<script src="${http_root}js/bootstrap3/bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/script.js"></script>
|
<script src="${http_root}js/script.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$('#updateDismiss').click(function() {
|
$('#updateDismiss').click(function() {
|
||||||
$('#updatebar').slideUp('slow');
|
$('#updatebar').slideUp('slow');
|
||||||
|
|
|
@ -2791,4 +2791,70 @@ a.no-highlight:hover {
|
||||||
#recently-added-row-scroller,
|
#recently-added-row-scroller,
|
||||||
#recently-watched-row-scroller {
|
#recently-watched-row-scroller {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.login-container {
|
||||||
|
max-width: 750px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.login-container {
|
||||||
|
max-width: 970px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.login-container {
|
||||||
|
max-width: 1170px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.login-container {
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
.login {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.login-logo {
|
||||||
|
background-image: url(../images/logo-plexpy@2x.png);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
margin: 0 auto 50px auto;
|
||||||
|
width: 340px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.login-container .form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.login-container .form-group label {
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.login-container .form-control {
|
||||||
|
height: 38px;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
.login-container .form-footer {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
.login-container .login-button {
|
||||||
|
float: right;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: 0 -1px 1px rgba(0,0,0,.4),0 0 15px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
.login-container .remember-group {
|
||||||
|
display: block;
|
||||||
|
min-height: 24px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.login-container .remember-group .control-label {
|
||||||
|
display: inline;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -248,12 +248,12 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/moment-duration-format.js"></script>
|
<script src="${http_root}js/moment-duration-format.js"></script>
|
||||||
<script src="interfaces/default/js/highcharts/js/highcharts.js"></script>
|
<script src="${http_root}js/highcharts/js/highcharts.js"></script>
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Modal popup dialog
|
// Modal popup dialog
|
||||||
|
@ -302,17 +302,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_day.js"></script>
|
<script src="${http_root}js/graphs/plays_by_day.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_dayofweek.js"></script>
|
<script src="${http_root}js/graphs/plays_by_dayofweek.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_hourofday.js"></script>
|
<script src="${http_root}js/graphs/plays_by_hourofday.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_platform.js"></script>
|
<script src="${http_root}js/graphs/plays_by_platform.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_user.js"></script>
|
<script src="${http_root}js/graphs/plays_by_user.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_stream_type.js"></script>
|
<script src="${http_root}js/graphs/plays_by_stream_type.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_source_resolution.js"></script>
|
<script src="${http_root}js/graphs/plays_by_source_resolution.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_stream_resolution.js"></script>
|
<script src="${http_root}js/graphs/plays_by_stream_resolution.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_platform_by_stream_type.js"></script>
|
<script src="${http_root}js/graphs/plays_by_platform_by_stream_type.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_user_by_stream_type.js"></script>
|
<script src="${http_root}js/graphs/plays_by_user_by_stream_type.js"></script>
|
||||||
<script src="interfaces/default/js/graphs/plays_by_month.js"></script>
|
<script src="${http_root}js/graphs/plays_by_month.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -69,12 +69,12 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
<script src="${http_root}js/tables/history_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
function loadHistoryTable(media_type) {
|
function loadHistoryTable(media_type) {
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
|
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
|
||||||
</div>
|
</div>
|
||||||
<script src="interfaces/default/js/tables/history_table_modal.js"></script>
|
<script src="${http_root}js/tables/history_table_modal.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#date-header').html(moment('${data["start_date"]}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
|
$('#date-header').html(moment('${data["start_date"]}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
|
||||||
|
|
|
@ -101,7 +101,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -137,7 +137,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -177,7 +177,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -209,7 +209,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -253,7 +253,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -289,7 +289,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -329,7 +329,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -361,7 +361,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -405,7 +405,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -441,7 +441,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -481,7 +481,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -513,7 +513,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster2">
|
<div class="home-platforms-instance-poster2">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -565,7 +565,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-oval" style="background-image: url(interfaces/default/images/gravatar-default.png);"></div>
|
<div class="home-platforms-instance-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -609,7 +609,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-list-oval" style="background-image: url(interfaces/default/images/gravatar-default.png);"></div>
|
<div class="home-platforms-instance-list-oval" style="background-image: url(${http_root}images/gravatar-default.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -644,7 +644,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
<div id="platform-stat" class="home-platforms-instance-poster" title="${top_stat['rows'][0]['platform_type']}">
|
<div id="platform-stat" class="home-platforms-instance-poster" title="${top_stat['rows'][0]['platform_type']}">
|
||||||
<script>
|
<script>
|
||||||
$("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][0]['platform_type']}') + ");'>");
|
$("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath("${top_stat['rows'][0]['platform_type']}") + ");'>");
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
% if len(top_stat['rows']) > 1:
|
% if len(top_stat['rows']) > 1:
|
||||||
|
@ -672,7 +672,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
<div class="home-platforms-instance-poster" id="home-platforms-instance-poster-${loop.index + 1}" title="${top_stat['rows'][loop.index]['platform_type']}">
|
<div class="home-platforms-instance-poster" id="home-platforms-instance-poster-${loop.index + 1}" title="${top_stat['rows'][loop.index]['platform_type']}">
|
||||||
<script>
|
<script>
|
||||||
$("#home-platforms-instance-poster-${loop.index + 1}").html("<div class='home-platforms-instance-list-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][loop.index]['platform_type']}') + ");'>");
|
$("#home-platforms-instance-poster-${loop.index + 1}").html("<div class='home-platforms-instance-list-box' style='background-image: url(" + getPlatformImagePath("${top_stat['rows'][loop.index]['platform_type']}") + ");'>");
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
<div class="home-platforms-instance-list-number">
|
<div class="home-platforms-instance-list-number">
|
||||||
|
@ -725,7 +725,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -771,7 +771,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="home-platforms-instance-list-poster">
|
<div class="home-platforms-instance-list-poster">
|
||||||
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
|
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
</a>
|
</a>
|
||||||
|
@ -807,7 +807,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-box" style="background-image: url(interfaces/default/images/home-stat_most-concurrent.png);"></div>
|
<div class="home-platforms-instance-box" style="background-image: url(${http_root}images/home-stat_most-concurrent.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
% if len(top_stat['rows']) > 1:
|
% if len(top_stat['rows']) > 1:
|
||||||
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
|
||||||
|
@ -839,7 +839,7 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="home-platforms-instance-poster">
|
<div class="home-platforms-instance-poster">
|
||||||
<div class="home-platforms-instance-list-box" style="background-image: url(interfaces/default/images/home-stat_most-concurrent.png);"></div>
|
<div class="home-platforms-instance-list-box" style="background-image: url(${http_root}images/home-stat_most-concurrent.png);"></div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function currentActivityHeader() {
|
function currentActivityHeader() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|
|
@ -57,9 +57,9 @@ DOCUMENTATION :: END
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -172,16 +172,16 @@ DOCUMENTATION :: END
|
||||||
% if data['media_type'] == 'movie' or data['media_type'] == 'episode' or data['media_type'] == 'track':
|
% if data['media_type'] == 'movie' or data['media_type'] == 'episode' or data['media_type'] == 'track':
|
||||||
<div class="summary-content-media-info-wrapper">
|
<div class="summary-content-media-info-wrapper">
|
||||||
% if data['media_type'] != 'track' and data['video_codec']:
|
% if data['media_type'] != 'track' and data['video_codec']:
|
||||||
<img class="summary-content-media-flag" title="${data['video_codec']}" src="interfaces/default/images/media_flags/video_codec/${data['video_codec'] | vf}.png" />
|
<img class="summary-content-media-flag" title="${data['video_codec']}" src="${http_root}images/media_flags/video_codec/${data['video_codec'] | vf}.png" />
|
||||||
% endif
|
% endif
|
||||||
% if data['media_type'] != 'track' and data['video_resolution']:
|
% if data['media_type'] != 'track' and data['video_resolution']:
|
||||||
<img class="summary-content-media-flag" title="${data['video_resolution']}" src="interfaces/default/images/media_flags/video_resolution/${data['video_resolution']}.png" />
|
<img class="summary-content-media-flag" title="${data['video_resolution']}" src="${http_root}images/media_flags/video_resolution/${data['video_resolution']}.png" />
|
||||||
% endif
|
% endif
|
||||||
% if data['audio_codec']:
|
% if data['audio_codec']:
|
||||||
<img class="summary-content-media-flag" title="${data['audio_codec']}" src="interfaces/default/images/media_flags/audio_codec/${data['audio_codec'] | af}.png" />
|
<img class="summary-content-media-flag" title="${data['audio_codec']}" src="${http_root}images/media_flags/audio_codec/${data['audio_codec'] | af}.png" />
|
||||||
% endif
|
% endif
|
||||||
% if data['audio_channels']:
|
% if data['audio_channels']:
|
||||||
<img class="summary-content-media-flag" title="${data['audio_channels']}" src="interfaces/default/images/media_flags/audio_channels/${data['audio_channels']}.png" />
|
<img class="summary-content-media-flag" title="${data['audio_channels']}" src="${http_root}images/media_flags/audio_channels/${data['audio_channels']}.png" />
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
@ -415,15 +415,15 @@ DOCUMENTATION :: END
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.rateit.min.js"></script>
|
<script src="${http_root}js/jquery.rateit.min.js"></script>
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
|
|
||||||
% if data:
|
% if data:
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
<script src="${http_root}js/tables/history_table.js"></script>
|
||||||
<!-- Need to find a place to put this -->
|
<!-- Need to find a place to put this -->
|
||||||
% if data['media_type'] == 'show' or data['media_type'] == 'artist':
|
% if data['media_type'] == 'show' or data['media_type'] == 'artist':
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -177,63 +177,63 @@ function resetFilters(text){
|
||||||
function getPlatformImagePath(platformName) {
|
function getPlatformImagePath(platformName) {
|
||||||
|
|
||||||
if (platformName.indexOf("Roku") > -1) {
|
if (platformName.indexOf("Roku") > -1) {
|
||||||
return 'interfaces/default/images/platforms/roku.png';
|
return 'images/platforms/roku.png';
|
||||||
} else if (platformName.indexOf("Apple TV") > -1) {
|
} else if (platformName.indexOf("Apple TV") > -1) {
|
||||||
return 'interfaces/default/images/platforms/atv.png';
|
return 'images/platforms/atv.png';
|
||||||
} else if (platformName.indexOf("tvOS") > -1) {
|
} else if (platformName.indexOf("tvOS") > -1) {
|
||||||
return 'interfaces/default/images/platforms/atv.png';
|
return 'images/platforms/atv.png';
|
||||||
} else if (platformName.indexOf("Firefox") > -1) {
|
} else if (platformName.indexOf("Firefox") > -1) {
|
||||||
return 'interfaces/default/images/platforms/firefox.png';
|
return 'images/platforms/firefox.png';
|
||||||
} else if (platformName.indexOf("Chromecast") > -1) {
|
} else if (platformName.indexOf("Chromecast") > -1) {
|
||||||
return 'interfaces/default/images/platforms/chromecast.png';
|
return 'images/platforms/chromecast.png';
|
||||||
} else if (platformName.indexOf("Chrome") > -1) {
|
} else if (platformName.indexOf("Chrome") > -1) {
|
||||||
return 'interfaces/default/images/platforms/chrome.png';
|
return 'images/platforms/chrome.png';
|
||||||
} else if (platformName.indexOf("Android") > -1) {
|
} else if (platformName.indexOf("Android") > -1) {
|
||||||
return 'interfaces/default/images/platforms/android.png';
|
return 'images/platforms/android.png';
|
||||||
} else if (platformName.indexOf("Nexus") > -1) {
|
} else if (platformName.indexOf("Nexus") > -1) {
|
||||||
return 'interfaces/default/images/platforms/android.png';
|
return 'images/platforms/android.png';
|
||||||
} else if (platformName.indexOf("iPad") > -1) {
|
} else if (platformName.indexOf("iPad") > -1) {
|
||||||
return 'interfaces/default/images/platforms/ios.png';
|
return 'images/platforms/ios.png';
|
||||||
} else if (platformName.indexOf("iPhone") > -1) {
|
} else if (platformName.indexOf("iPhone") > -1) {
|
||||||
return 'interfaces/default/images/platforms/ios.png';
|
return 'images/platforms/ios.png';
|
||||||
} else if (platformName.indexOf("iOS") > -1) {
|
} else if (platformName.indexOf("iOS") > -1) {
|
||||||
return 'interfaces/default/images/platforms/ios.png';
|
return 'images/platforms/ios.png';
|
||||||
} else if (platformName.indexOf("Plex Home Theater") > -1) {
|
} else if (platformName.indexOf("Plex Home Theater") > -1) {
|
||||||
return 'interfaces/default/images/platforms/pht.png';
|
return 'images/platforms/pht.png';
|
||||||
} else if (platformName.indexOf("Linux/RPi-XMBC") > -1) {
|
} else if (platformName.indexOf("Linux/RPi-XMBC") > -1) {
|
||||||
return 'interfaces/default/images/platforms/xbmc.png';
|
return 'images/platforms/xbmc.png';
|
||||||
} else if (platformName.indexOf("Safari") > -1) {
|
} else if (platformName.indexOf("Safari") > -1) {
|
||||||
return 'interfaces/default/images/platforms/safari.png';
|
return 'images/platforms/safari.png';
|
||||||
} else if (platformName.indexOf("Internet Explorer") > -1) {
|
} else if (platformName.indexOf("Internet Explorer") > -1) {
|
||||||
return 'interfaces/default/images/platforms/ie.png';
|
return 'images/platforms/ie.png';
|
||||||
} else if (platformName.indexOf("Microsoft Edge") > -1) {
|
} else if (platformName.indexOf("Microsoft Edge") > -1) {
|
||||||
return 'interfaces/default/images/platforms/msedge.png';
|
return 'images/platforms/msedge.png';
|
||||||
} else if (platformName.indexOf("Unknown Browser") > -1) {
|
} else if (platformName.indexOf("Unknown Browser") > -1) {
|
||||||
return 'interfaces/default/images/platforms/dafault.png';
|
return 'images/platforms/dafault.png';
|
||||||
} else if (platformName.indexOf("Windows-XBMC") > -1) {
|
} else if (platformName.indexOf("Windows-XBMC") > -1) {
|
||||||
return 'interfaces/default/images/platforms/xbmc.png';
|
return 'images/platforms/xbmc.png';
|
||||||
} else if (platformName.indexOf("Xbox") > -1) {
|
} else if (platformName.indexOf("Xbox") > -1) {
|
||||||
return 'interfaces/default/images/platforms/xbox.png';
|
return 'images/platforms/xbox.png';
|
||||||
} else if (platformName.indexOf("Samsung") > -1) {
|
} else if (platformName.indexOf("Samsung") > -1) {
|
||||||
return 'interfaces/default/images/platforms/samsung.png';
|
return 'images/platforms/samsung.png';
|
||||||
} else if (platformName.indexOf("Opera") > -1) {
|
} else if (platformName.indexOf("Opera") > -1) {
|
||||||
return 'interfaces/default/images/platforms/opera.png';
|
return 'images/platforms/opera.png';
|
||||||
} else if (platformName.indexOf("KODI") > -1) {
|
} else if (platformName.indexOf("KODI") > -1) {
|
||||||
return 'interfaces/default/images/platforms/kodi.png';
|
return 'images/platforms/kodi.png';
|
||||||
} else if (platformName.indexOf("Playstation 3") > -1) {
|
} else if (platformName.indexOf("Playstation 3") > -1) {
|
||||||
return 'interfaces/default/images/platforms/playstation.png';
|
return 'images/platforms/playstation.png';
|
||||||
} else if (platformName.indexOf("Playstation 4") > -1) {
|
} else if (platformName.indexOf("Playstation 4") > -1) {
|
||||||
return 'interfaces/default/images/platforms/playstation.png';
|
return 'images/platforms/playstation.png';
|
||||||
} else if (platformName.indexOf("Xbox 360") > -1) {
|
} else if (platformName.indexOf("Xbox 360") > -1) {
|
||||||
return 'interfaces/default/images/platforms/xbox.png';
|
return 'images/platforms/xbox.png';
|
||||||
} else if (platformName.indexOf("Windows") > -1) {
|
} else if (platformName.indexOf("Windows") > -1) {
|
||||||
return 'interfaces/default/images/platforms/win8.png';
|
return 'images/platforms/win8.png';
|
||||||
} else if (platformName.indexOf("Windows phone") > -1) {
|
} else if (platformName.indexOf("Windows phone") > -1) {
|
||||||
return 'interfaces/default/images/platforms/wp.png';
|
return 'images/platforms/wp.png';
|
||||||
} else if (platformName.indexOf("Plex Media Player") > -1) {
|
} else if (platformName.indexOf("Plex Media Player") > -1) {
|
||||||
return 'interfaces/default/images/platforms/pmp.png';
|
return 'images/platforms/pmp.png';
|
||||||
} else {
|
} else {
|
||||||
return 'interfaces/default/images/platforms/default.png';
|
return 'images/platforms/default.png';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ libraries_list_table_options = {
|
||||||
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(pms_image_proxy?img=' + rowData['library_thumb'] + '&width=80&height=80&fallback=poster);"></div></a>');
|
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(pms_image_proxy?img=' + rowData['library_thumb'] + '&width=80&height=80&fallback=poster);"></div></a>');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(interfaces/default/images/cover.png);"></div></a>');
|
$(td).html('<a href="library?section_id=' + rowData['section_id'] + '"><div class="libraries-poster-face" style="background-image: url(../../images/cover.png);"></div></a>');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"orderable": false,
|
"orderable": false,
|
||||||
|
|
|
@ -57,7 +57,7 @@ users_list_table_options = {
|
||||||
"data": "user_thumb",
|
"data": "user_thumb",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData === '') {
|
if (cellData === '') {
|
||||||
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(interfaces/default/images/gravatar-default-80x80.png);"></div></a>');
|
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(../../images/gravatar-default-80x80.png);"></div></a>');
|
||||||
} else {
|
} else {
|
||||||
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(' + rowData['user_thumb'] + ');"></div></a>');
|
$(td).html('<a href="user?user_id=' + rowData['user_id'] + '"><div class="users-poster-face" style="background-image: url(' + rowData['user_thumb'] + ');"></div></a>');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -81,12 +81,12 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/libraries.js"></script>
|
<script src="${http_root}js/tables/libraries.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
libraries_list_table_options.ajax = {
|
libraries_list_table_options.ajax = {
|
||||||
|
|
|
@ -28,9 +28,9 @@ DOCUMENTATION :: END
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -321,10 +321,10 @@ DOCUMENTATION :: END
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
% if data:
|
% if data:
|
||||||
<script>
|
<script>
|
||||||
% if str(data['section_id']).isdigit():
|
% if str(data['section_id']).isdigit():
|
||||||
|
@ -341,9 +341,9 @@ DOCUMENTATION :: END
|
||||||
var get_file_sizes = null;
|
var get_file_sizes = null;
|
||||||
% endif
|
% endif
|
||||||
</script>
|
</script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
<script src="${http_root}js/tables/history_table.js"></script>
|
||||||
<script src="interfaces/default/js/tables/media_info_table.js"></script>
|
<script src="${http_root}js/tables/media_info_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$("#edit-library-tooltip").tooltip();
|
$("#edit-library-tooltip").tooltip();
|
||||||
|
|
66
data/interfaces/default/login.html
Normal file
66
data/interfaces/default/login.html
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>PlexPy - ${title}</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
|
||||||
|
<link href="${http_root}css/bootstrap-wizard.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="${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>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="body-container">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="login-container">
|
||||||
|
<div class="login-logo"></div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-sm-offset-3">
|
||||||
|
<form action="${http_root}auth/login" method="post">
|
||||||
|
% if msg:
|
||||||
|
<div class="alert alert-danger" style="text-align: center; padding: 8px;">
|
||||||
|
${msg}
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
<div class="username-group form-group">
|
||||||
|
<label for="username" class="control-label">
|
||||||
|
Username
|
||||||
|
</label>
|
||||||
|
<input type="text" id="username" name="username" class="form-control" autocorrect="off" autocapitalize="off" value="${username}">
|
||||||
|
</div>
|
||||||
|
<div class="password-group form-group">
|
||||||
|
<label for="password" class="control-label">
|
||||||
|
Password
|
||||||
|
</label>
|
||||||
|
<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>
|
||||||
|
<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
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
|
||||||
|
<script src="${http_root}js/bootstrap3/bootstrap.min.js"></script>
|
||||||
|
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -4,8 +4,8 @@ from plexpy import helpers
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
<style>
|
<style>
|
||||||
td {word-break: break-all;}
|
td {word-break: break-all;}
|
||||||
</style>
|
</style>
|
||||||
|
@ -107,13 +107,13 @@ from plexpy import helpers
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/logs.js"></script>
|
<script src="${http_root}js/tables/logs.js"></script>
|
||||||
<script src="interfaces/default/js/tables/plex_logs.js"></script>
|
<script src="${http_root}js/tables/plex_logs.js"></script>
|
||||||
<script src="interfaces/default/js/tables/notification_logs.js"></script>
|
<script src="${http_root}js/tables/notification_logs.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
|
@ -1918,9 +1918,9 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/parsley.min.js"></script>
|
<script src="${http_root}js/parsley.min.js"></script>
|
||||||
<script src="interfaces/default/js/Sortable.min.js"></script>
|
<script src="${http_root}js/Sortable.min.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<style>
|
<style>
|
||||||
td {word-wrap: break-word}
|
td {word-wrap: break-word}
|
||||||
</style>
|
</style>
|
||||||
|
@ -46,11 +46,11 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/tables/sync_table.js"></script>
|
<script src="${http_root}js/tables/sync_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
sync_table_options.ajax = {
|
sync_table_options.ajax = {
|
||||||
|
|
|
@ -30,9 +30,9 @@ from plexpy import helpers
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -301,15 +301,15 @@ from plexpy import helpers
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
% if data:
|
% if data:
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
<script src="${http_root}js/tables/history_table.js"></script>
|
||||||
<script src="interfaces/default/js/tables/user_ips.js"></script>
|
<script src="${http_root}js/tables/user_ips.js"></script>
|
||||||
<script src="interfaces/default/js/tables/sync_table.js"></script>
|
<script src="${http_root}js/tables/sync_table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<%inherit file="base.html"/>
|
<%inherit file="base.html"/>
|
||||||
|
|
||||||
<%def name="headIncludes()">
|
<%def name="headIncludes()">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.bootstrap.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.bootstrap.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/dataTables.colVis.css">
|
<link rel="stylesheet" href="${http_root}css/dataTables.colVis.css">
|
||||||
<link rel="stylesheet" href="interfaces/default/css/plexpy-dataTables.css">
|
<link rel="stylesheet" href="${http_root}css/plexpy-dataTables.css">
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="body()">
|
<%def name="body()">
|
||||||
|
@ -69,12 +69,12 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="javascriptIncludes()">
|
<%def name="javascriptIncludes()">
|
||||||
<script src="interfaces/default/js/jquery.dataTables.min.js"></script>
|
<script src="${http_root}js/jquery.dataTables.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.colVis.js"></script>
|
<script src="${http_root}js/dataTables.colVis.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.min.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/dataTables.bootstrap.pagination.js"></script>
|
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
|
||||||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
<script src="${http_root}js/moment-with-locale.js"></script>
|
||||||
<script src="interfaces/default/js/tables/users.js"></script>
|
<script src="${http_root}js/tables/users.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
users_list_table_options.ajax = {
|
users_list_table_options.ajax = {
|
||||||
|
|
|
@ -12,14 +12,14 @@ from plexpy import common
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
<link href="interfaces/default/css/bootstrap3/bootstrap.css" rel="stylesheet">
|
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
|
||||||
<link href="interfaces/default/css/bootstrap-wizard.css" rel="stylesheet">
|
<link href="${http_root}css/bootstrap-wizard.css" rel="stylesheet">
|
||||||
<link href="interfaces/default/css/plexpy.css" rel="stylesheet">
|
<link href="${http_root}css/plexpy.css" rel="stylesheet">
|
||||||
<link href="interfaces/default/css/selectize.bootstrap3.css" rel="stylesheet">
|
<link href="${http_root}css/selectize.bootstrap3.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" rel="stylesheet" type="text/css">
|
||||||
<link href="interfaces/default/css/font-awesome.min.css" rel="stylesheet">
|
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
|
||||||
<link rel="icon" type="image/x-icon" href="interfaces/default/images/favicon.ico"/>
|
<link rel="icon" type="image/x-icon" href="${http_root}images/favicon.ico"/>
|
||||||
<link rel="shortcut icon" href="interfaces/default/images/favicon.ico">
|
<link rel="shortcut icon" href="${http_root}images/favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -28,7 +28,7 @@ from plexpy import common
|
||||||
<div class="wizard" id="some-wizard" data-title="PlexPy Setup Wizard">
|
<div class="wizard" id="some-wizard" data-title="PlexPy Setup Wizard">
|
||||||
<div class="wizard-card" data-cardname="card1">
|
<div class="wizard-card" data-cardname="card1">
|
||||||
<div style="float: right;">
|
<div style="float: right;">
|
||||||
<img src="interfaces/default/images/logo-plexpy.png"/>
|
<img src="${http_root}images/logo-plexpy.png"/>
|
||||||
</div>
|
</div>
|
||||||
<h3 style="line-height: 50px;">Welcome!</h3>
|
<h3 style="line-height: 50px;">Welcome!</h3>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -191,11 +191,11 @@ from plexpy import common
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="interfaces/default/js/jquery-2.1.4.min.js"></script>
|
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
|
||||||
<script src="interfaces/default/js/bootstrap3/bootstrap.min.js"></script>
|
<script src="${http_root}js/bootstrap3/bootstrap.min.js"></script>
|
||||||
<script src="interfaces/default/js/selectize.min.js"></script>
|
<script src="${http_root}js/selectize.min.js"></script>
|
||||||
<script src="interfaces/default/js/script.js"></script>
|
<script src="${http_root}js/script.js"></script>
|
||||||
<script src="interfaces/default/js/bootstrap-wizard.min.js"></script>
|
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
|
@ -74,6 +74,8 @@ UMASK = None
|
||||||
|
|
||||||
POLLING_FAILOVER = False
|
POLLING_FAILOVER = False
|
||||||
|
|
||||||
|
HTTP_ROOT = None
|
||||||
|
|
||||||
DEV = False
|
DEV = False
|
||||||
|
|
||||||
|
|
||||||
|
|
158
plexpy/webauth.py
Normal file
158
plexpy/webauth.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
# This file is part of PlexPy.
|
||||||
|
#
|
||||||
|
# PlexPy is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PlexPy is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
# http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions
|
||||||
|
# Form based authentication for CherryPy. Requires the
|
||||||
|
# Session tool to be loaded.
|
||||||
|
|
||||||
|
import cherrypy
|
||||||
|
from cgi import escape
|
||||||
|
|
||||||
|
import plexpy
|
||||||
|
from plexpy import logger
|
||||||
|
|
||||||
|
|
||||||
|
SESSION_KEY = '_cp_username'
|
||||||
|
|
||||||
|
def check_credentials(username, password):
|
||||||
|
"""Verifies credentials for username and password.
|
||||||
|
Returns None on success or a string describing the error on failure"""
|
||||||
|
# Adapt to your needs
|
||||||
|
if username == plexpy.CONFIG.HTTP_USERNAME and password == plexpy.CONFIG.HTTP_PASSWORD:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return u"Incorrect username or password."
|
||||||
|
|
||||||
|
# An example implementation which uses an ORM could be:
|
||||||
|
# u = User.get(username)
|
||||||
|
# if u is None:
|
||||||
|
# return u"Username %s is unknown to me." % username
|
||||||
|
# if u.password != md5.new(password).hexdigest():
|
||||||
|
# return u"Incorrect password"
|
||||||
|
|
||||||
|
def check_auth(*args, **kwargs):
|
||||||
|
"""A tool that looks in config for 'auth.require'. If found and it
|
||||||
|
is not None, a login is required and the entry is evaluated as a list of
|
||||||
|
conditions that the user must fulfill"""
|
||||||
|
conditions = cherrypy.request.config.get('auth.require', None)
|
||||||
|
if conditions is not None:
|
||||||
|
username = cherrypy.session.get(SESSION_KEY)
|
||||||
|
if username:
|
||||||
|
cherrypy.request.login = username
|
||||||
|
for condition in conditions:
|
||||||
|
# A condition is just a callable that returns true or false
|
||||||
|
if not condition():
|
||||||
|
raise cherrypy.HTTPRedirect("auth/login")
|
||||||
|
else:
|
||||||
|
raise cherrypy.HTTPRedirect("auth/login")
|
||||||
|
|
||||||
|
def require(*conditions):
|
||||||
|
"""A decorator that appends conditions to the auth.require config
|
||||||
|
variable."""
|
||||||
|
def decorate(f):
|
||||||
|
if not hasattr(f, '_cp_config'):
|
||||||
|
f._cp_config = dict()
|
||||||
|
if 'auth.require' not in f._cp_config:
|
||||||
|
f._cp_config['auth.require'] = []
|
||||||
|
f._cp_config['auth.require'].extend(conditions)
|
||||||
|
return f
|
||||||
|
return decorate
|
||||||
|
|
||||||
|
|
||||||
|
# Conditions are callables that return True
|
||||||
|
# if the user fulfills the conditions they define, False otherwise
|
||||||
|
#
|
||||||
|
# They can access the current username as cherrypy.request.login
|
||||||
|
#
|
||||||
|
# Define those at will however suits the application.
|
||||||
|
|
||||||
|
def member_of(groupname):
|
||||||
|
def check():
|
||||||
|
# replace with actual check if <username> is in <groupname>
|
||||||
|
return cherrypy.request.login == plexpy.CONFIG.HTTP_USERNAME and groupname == 'admin'
|
||||||
|
return check
|
||||||
|
|
||||||
|
def name_is(reqd_username):
|
||||||
|
return lambda: reqd_username == cherrypy.request.login
|
||||||
|
|
||||||
|
# These might be handy
|
||||||
|
|
||||||
|
def any_of(*conditions):
|
||||||
|
"""Returns True if any of the conditions match"""
|
||||||
|
def check():
|
||||||
|
for c in conditions:
|
||||||
|
if c():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return check
|
||||||
|
|
||||||
|
# By default all conditions are required, but this might still be
|
||||||
|
# needed if you want to use it inside of an any_of(...) condition
|
||||||
|
def all_of(*conditions):
|
||||||
|
"""Returns True if all of the conditions match"""
|
||||||
|
def check():
|
||||||
|
for c in conditions:
|
||||||
|
if not c():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return check
|
||||||
|
|
||||||
|
|
||||||
|
# Controller to provide login and logout actions
|
||||||
|
|
||||||
|
class AuthController(object):
|
||||||
|
|
||||||
|
def on_login(self, username):
|
||||||
|
"""Called on successful login"""
|
||||||
|
logger.debug(u"User '%s' logged into PlexPy." % username)
|
||||||
|
|
||||||
|
def on_logout(self, username):
|
||||||
|
"""Called on logout"""
|
||||||
|
logger.debug(u"User '%s' logged out of PlexPy." % username)
|
||||||
|
|
||||||
|
def get_loginform(self, username="", msg=""):
|
||||||
|
from plexpy.webserve import serve_template
|
||||||
|
|
||||||
|
username = escape(username, True)
|
||||||
|
|
||||||
|
return serve_template(templatename="login.html", title="Welcome", username=username, msg=msg)
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def login(self, username=None, password=None, remember_me=0):
|
||||||
|
if username is None or password is None:
|
||||||
|
return self.get_loginform()
|
||||||
|
|
||||||
|
error_msg = check_credentials(username, password)
|
||||||
|
|
||||||
|
if error_msg:
|
||||||
|
logger.debug(u"Invalid login attempt from '%s'." % username)
|
||||||
|
return self.get_loginform(username, error_msg)
|
||||||
|
else:
|
||||||
|
cherrypy.session.regenerate()
|
||||||
|
cherrypy.session[SESSION_KEY] = cherrypy.request.login = username
|
||||||
|
self.on_login(username)
|
||||||
|
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT or "/")
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
def logout(self):
|
||||||
|
sess = cherrypy.session
|
||||||
|
username = sess.get(SESSION_KEY, None)
|
||||||
|
sess[SESSION_KEY] = None
|
||||||
|
|
||||||
|
if username:
|
||||||
|
cherrypy.request.login = None
|
||||||
|
self.on_logout(username)
|
||||||
|
raise cherrypy.HTTPRedirect("login")
|
|
@ -16,6 +16,7 @@
|
||||||
from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, \
|
from plexpy import logger, notifiers, plextv, pmsconnect, common, log_reader, \
|
||||||
datafactory, graphs, users, libraries, database, web_socket
|
datafactory, graphs, users, libraries, database, web_socket
|
||||||
from plexpy.helpers import checked, addtoapi, get_ip, create_https_certificates
|
from plexpy.helpers import checked, addtoapi, get_ip, create_https_certificates
|
||||||
|
from plexpy.webauth import AuthController, require, member_of, name_is
|
||||||
|
|
||||||
from mako.lookup import TemplateLookup
|
from mako.lookup import TemplateLookup
|
||||||
from mako import exceptions
|
from mako import exceptions
|
||||||
|
@ -49,17 +50,20 @@ def serve_template(templatename, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
template = _hplookup.get_template(templatename)
|
template = _hplookup.get_template(templatename)
|
||||||
return template.render(server_name=server_name, **kwargs)
|
return template.render(server_name=server_name, http_root=plexpy.HTTP_ROOT, **kwargs)
|
||||||
except:
|
except:
|
||||||
return exceptions.html_error_template().render()
|
return exceptions.html_error_template().render()
|
||||||
|
|
||||||
|
|
||||||
class WebInterface(object):
|
class WebInterface(object):
|
||||||
|
|
||||||
|
auth = AuthController()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.interface_dir = os.path.join(str(plexpy.PROG_DIR), 'data/')
|
self.interface_dir = os.path.join(str(plexpy.PROG_DIR), 'data/')
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def index(self):
|
def index(self):
|
||||||
if plexpy.CONFIG.FIRST_RUN_COMPLETE:
|
if plexpy.CONFIG.FIRST_RUN_COMPLETE:
|
||||||
raise cherrypy.HTTPRedirect("home")
|
raise cherrypy.HTTPRedirect("home")
|
||||||
|
@ -142,6 +146,7 @@ class WebInterface(object):
|
||||||
##### Home #####
|
##### Home #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def home(self):
|
def home(self):
|
||||||
config = {
|
config = {
|
||||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||||
|
@ -270,6 +275,7 @@ class WebInterface(object):
|
||||||
##### Libraries #####
|
##### Libraries #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def libraries(self):
|
def libraries(self):
|
||||||
config = {
|
config = {
|
||||||
"update_section_ids": plexpy.CONFIG.UPDATE_SECTION_IDS
|
"update_section_ids": plexpy.CONFIG.UPDATE_SECTION_IDS
|
||||||
|
@ -578,6 +584,7 @@ class WebInterface(object):
|
||||||
##### Users #####
|
##### Users #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def users(self):
|
def users(self):
|
||||||
return serve_template(templatename="users.html", title="Users")
|
return serve_template(templatename="users.html", title="Users")
|
||||||
|
|
||||||
|
@ -749,6 +756,7 @@ class WebInterface(object):
|
||||||
##### History #####
|
##### History #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def history(self):
|
def history(self):
|
||||||
return serve_template(templatename="history.html", title="History")
|
return serve_template(templatename="history.html", title="History")
|
||||||
|
|
||||||
|
@ -837,6 +845,7 @@ class WebInterface(object):
|
||||||
##### Graphs #####
|
##### Graphs #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def graphs(self):
|
def graphs(self):
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
|
@ -1024,6 +1033,7 @@ class WebInterface(object):
|
||||||
##### Sync #####
|
##### Sync #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def sync(self):
|
def sync(self):
|
||||||
return serve_template(templatename="sync.html", title="Synced Items")
|
return serve_template(templatename="sync.html", title="Synced Items")
|
||||||
|
|
||||||
|
@ -1049,6 +1059,7 @@ class WebInterface(object):
|
||||||
##### Logs #####
|
##### Logs #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def logs(self):
|
def logs(self):
|
||||||
return serve_template(templatename="logs.html", title="Log", lineList=plexpy.LOG_LIST)
|
return serve_template(templatename="logs.html", title="Log", lineList=plexpy.LOG_LIST)
|
||||||
|
|
||||||
|
@ -1167,6 +1178,7 @@ class WebInterface(object):
|
||||||
##### Settings #####
|
##### Settings #####
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
|
@require()
|
||||||
def settings(self):
|
def settings(self):
|
||||||
interface_dir = os.path.join(plexpy.PROG_DIR, 'data/interfaces/')
|
interface_dir = os.path.join(plexpy.PROG_DIR, 'data/interfaces/')
|
||||||
interface_list = [name for name in os.listdir(interface_dir) if
|
interface_list = [name for name in os.listdir(interface_dir) if
|
||||||
|
|
|
@ -17,7 +17,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import cherrypy
|
import cherrypy
|
||||||
from plexpy import logger
|
from plexpy import logger, webauth
|
||||||
import plexpy
|
import plexpy
|
||||||
from plexpy.helpers import create_https_certificates
|
from plexpy.helpers import create_https_certificates
|
||||||
from plexpy.webserve import WebInterface
|
from plexpy.webserve import WebInterface
|
||||||
|
@ -50,7 +50,7 @@ def initialize(options):
|
||||||
'server.thread_pool': 10,
|
'server.thread_pool': 10,
|
||||||
'tools.encode.on': True,
|
'tools.encode.on': True,
|
||||||
'tools.encode.encoding': 'utf-8',
|
'tools.encode.encoding': 'utf-8',
|
||||||
'tools.decode.on': True,
|
'tools.decode.on': True
|
||||||
}
|
}
|
||||||
|
|
||||||
if enable_https:
|
if enable_https:
|
||||||
|
@ -64,8 +64,17 @@ def initialize(options):
|
||||||
options_dict['environment'] = "test_suite"
|
options_dict['environment'] = "test_suite"
|
||||||
options_dict['engine.autoreload.on'] = True
|
options_dict['engine.autoreload.on'] = True
|
||||||
|
|
||||||
logger.info("Starting PlexPy web server on %s://%s:%d/", protocol,
|
if options['http_password']:
|
||||||
options['http_host'], options['http_port'])
|
logger.info("Web server authentication is enabled, username is '%s'", options['http_username'])
|
||||||
|
options_dict['tools.sessions.on'] = True
|
||||||
|
options_dict['tools.auth.on'] = True
|
||||||
|
cherrypy.tools.auth = cherrypy.Tool('before_handler', webauth.check_auth)
|
||||||
|
|
||||||
|
if not options['http_root'] or options['http_root'] == '/':
|
||||||
|
plexpy.HTTP_ROOT = options['http_root'] = '/'
|
||||||
|
else:
|
||||||
|
plexpy.HTTP_ROOT = options['http_root'] = '/' + options['http_root'].strip('/') + '/'
|
||||||
|
|
||||||
cherrypy.config.update(options_dict)
|
cherrypy.config.update(options_dict)
|
||||||
|
|
||||||
conf = {
|
conf = {
|
||||||
|
@ -83,15 +92,27 @@ def initialize(options):
|
||||||
},
|
},
|
||||||
'/images': {
|
'/images': {
|
||||||
'tools.staticdir.on': True,
|
'tools.staticdir.on': True,
|
||||||
'tools.staticdir.dir': "images"
|
'tools.staticdir.dir': "interfaces/default/images"
|
||||||
},
|
},
|
||||||
'/css': {
|
'/css': {
|
||||||
'tools.staticdir.on': True,
|
'tools.staticdir.on': True,
|
||||||
'tools.staticdir.dir': "css"
|
'tools.staticdir.dir': "interfaces/default/css"
|
||||||
|
},
|
||||||
|
'/fonts': {
|
||||||
|
'tools.staticdir.on': True,
|
||||||
|
'tools.staticdir.dir': "interfaces/default/fonts"
|
||||||
},
|
},
|
||||||
'/js': {
|
'/js': {
|
||||||
'tools.staticdir.on': True,
|
'tools.staticdir.on': True,
|
||||||
'tools.staticdir.dir': "js"
|
'tools.staticdir.dir': "interfaces/default/js"
|
||||||
|
},
|
||||||
|
'/json': {
|
||||||
|
'tools.staticdir.on': True,
|
||||||
|
'tools.staticdir.dir': "interfaces/default/json"
|
||||||
|
},
|
||||||
|
'/xml': {
|
||||||
|
'tools.staticdir.on': True,
|
||||||
|
'tools.staticdir.dir': "interfaces/default/xml"
|
||||||
},
|
},
|
||||||
'/cache': {
|
'/cache': {
|
||||||
'tools.staticdir.on': True,
|
'tools.staticdir.on': True,
|
||||||
|
@ -100,27 +121,19 @@ def initialize(options):
|
||||||
'/favicon.ico': {
|
'/favicon.ico': {
|
||||||
'tools.staticfile.on': True,
|
'tools.staticfile.on': True,
|
||||||
'tools.staticfile.filename': os.path.abspath(os.path.join(plexpy.PROG_DIR, 'data/interfaces/default/images/favicon.ico'))
|
'tools.staticfile.filename': os.path.abspath(os.path.join(plexpy.PROG_DIR, 'data/interfaces/default/images/favicon.ico'))
|
||||||
}
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if options['http_password']:
|
if options['http_password']:
|
||||||
logger.info("Web server authentication is enabled, username is '%s'", options['http_username'])
|
conf['/api'] = {'tools.auth.on': False}
|
||||||
|
|
||||||
conf['/'].update({
|
|
||||||
'tools.auth_basic.on': True,
|
|
||||||
'tools.auth_basic.realm': 'PlexPy web server',
|
|
||||||
'tools.auth_basic.checkpassword': cherrypy.lib.auth_basic.checkpassword_dict({
|
|
||||||
options['http_username']: options['http_password']
|
|
||||||
})
|
|
||||||
})
|
|
||||||
conf['/api'] = {'tools.auth_basic.on': False}
|
|
||||||
|
|
||||||
# Prevent time-outs
|
# Prevent time-outs
|
||||||
cherrypy.engine.timeout_monitor.unsubscribe()
|
cherrypy.engine.timeout_monitor.unsubscribe()
|
||||||
cherrypy.tree.mount(WebInterface(), str(options['http_root']), config=conf)
|
cherrypy.tree.mount(WebInterface(), options['http_root'], config=conf)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
logger.info("Starting PlexPy web server on %s://%s:%d%s", protocol,
|
||||||
|
options['http_host'], options['http_port'], options['http_root'])
|
||||||
cherrypy.process.servers.check_port(str(options['http_host']), options['http_port'])
|
cherrypy.process.servers.check_port(str(options['http_host']), options['http_port'])
|
||||||
if not plexpy.DEV:
|
if not plexpy.DEV:
|
||||||
cherrypy.server.start()
|
cherrypy.server.start()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue