Merge branch 'dev'

This commit is contained in:
Tim 2015-09-09 22:20:45 +02:00
commit eaadd5e2d6
9 changed files with 146 additions and 19 deletions

View file

@ -1,5 +1,14 @@
# Changelog # Changelog
## v1.1.8 (2015-09-09)
* Add platform images for Windows devices. Thanks @JonnyWong.
* Add click-through to PlexWeb preplay page from info page. Thanks @JonnyWong.
* Fix broken delete option on info pages. Thanks @JonnyWong.
* Fix tagline bug in PlexWatch db import tool.
* Fix home stats text overflow bug. Thanks @JonnyWong.
## v1.1.7 (2015-09-07) ## v1.1.7 (2015-09-07)
* Show tagline in info screens for movies. Thanks @JonnyWong. * Show tagline in info screens for movies. Thanks @JonnyWong.

View file

@ -1,5 +1,7 @@
#PlexPy #PlexPy
[![Join the chat at https://gitter.im/drzoidberg33/plexpy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/drzoidberg33/plexpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
A python based web application for monitoring, analytics and notifications for Plex Media Server (www.plex.tv). A python based web application for monitoring, analytics and notifications for Plex Media Server (www.plex.tv).
This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb). This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb).
@ -120,4 +122,4 @@ If you **comply with these rules** you can [post your request/issue](http://gith
## License ## License
This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included. This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included.
This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution. This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.

View file

@ -973,11 +973,40 @@ a .dashboard-activity-metadata-user-thumb:hover {
overflow: hidden; overflow: hidden;
z-index: 1; z-index: 1;
} }
a .summary-poster-face:hover, .summary-poster-face-overlay {
a .summary-poster-face-episode:hover { position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: -webkit-gradient(linear,left 0,left 100%,from(rgba(0,0,0,.7)),to(rgba(0,0,0,.9)));
background-image: -webkit-linear-gradient(top,rgba(0,0,0,.7),0,rgba(0,0,0,.9),100%);
background-image: -moz-linear-gradient(top,rgba(0,0,0,.7) 0,rgba(0,0,0,.9) 100%);
background-image: linear-gradient(to bottom,rgba(0,0,0,.7) 0,rgba(0,0,0,.9) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3000000', endColorstr='#e6000000', GradientType=0);
webkit-box-shadow: inset 0 0 0 2px #e9a049; webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049; -moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049; box-shadow: inset 0 0 0 2px #e9a049;
opacity: 0;
transition: opacity .2s;
}
.summary-poster-face-overlay span {
display: block;
width: 100%;
height: 100%;
background-image: url(/interfaces/default/images/plex-logo-light.svg);
background-size: 100px;
background-repeat: no-repeat;
background-position: center;
opacity: 0;
transition: opacity .3s;
}
a:hover .summary-poster-face .summary-poster-face-overlay,
a:hover .summary-poster-face-episode .summary-poster-face-overlay,
a:hover .summary-poster-face .summary-poster-face-overlay span,
a:hover .summary-poster-face-episode .summary-poster-face-overlay span {
opacity: 1;
} }
.summary-content-padding { .summary-content-padding {
float: left; float: left;
@ -1581,6 +1610,7 @@ a .season-episodes-card-overlay:hover {
display: inline-block; display: inline-block;
position: relative; position: relative;
padding: 6px 0 0 20px; padding: 6px 0 0 20px;
max-width: 100%;
} }
.home-platforms-instance-playcount h4 { .home-platforms-instance-playcount h4 {
font-size: 14px; font-size: 14px;

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="3086px" height="1000px" viewBox="0 0 3086 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>plex-logo-light</title>
<desc>Created with Sketch.</desc>
<defs>
<radialGradient cx="89.2670157%" cy="49.76%" fx="89.2670157%" fy="49.76%" r="92.4996161%" id="radialGradient-1">
<stop stop-color="#F9BE03" offset="0%"></stop>
<stop stop-color="#CC7C19" offset="100%"></stop>
</radialGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="plex-logo-light" sketch:type="MSArtboardGroup">
<g sketch:type="MSLayerGroup">
<path d="M3085.99,0 L2795.989,0 L2505.99,500 L2795.989,1000 L3085.737,1000 L2795.989,500.25 L3085.99,0" id="X" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<path d="M2186,0 L2476.00071,0 L2796,500.25 L2476.00071,1000.5 L2186,1000.5 L2505.99929,500.25 L2186,0" id="chevron" fill="url(#radialGradient-1)" sketch:type="MSShapeGroup"></path>
<path d="M2085.947,1000 L1508.874,1000 L1508.874,0 L2085.947,0 L2085.947,173.737 L1721.339,173.737 L1721.339,393.299 L2060.594,393.299 L2060.594,567.03 L1721.339,567.03 L1721.339,824.895 L2085.947,824.895 L2085.947,1000" id="E" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<path d="M791.276,1000 L791.276,0 L1003.316,0 L1003.316,824.895 L1408.925,824.895 L1408.925,1000 L791.276,1000" id="L" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<g id="P" fill="#FFFFFF" sketch:type="MSShapeGroup">
<path d="M589.947,558.824 C522.679,615.831 427.037,644.325 303.009,644.325 L212.04,644.325 L212.04,1000 L0,1000 L0,643.947829 L0,470.337388 L290,470.697418 C467.563171,468.627777 476.842468,359.878967 476.842468,322.200012 C476.842468,287.221283 476.842468,175.445374 319,173.699997 L0,173.703242 L0,0 L319.424,0 C440.717,0 532.939,26.107 596.101,78.321 C659.253,130.534 690.834,208.392 690.834,311.902 C690.834,419.527 657.202,501.83 589.947,558.824 Z" id="Path"></path>
<rect id="Path" x="0" y="110" width="212.2" height="429"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -81,13 +81,21 @@ DOCUMENTATION :: END
<div class="summary-content-title-wrapper"> <div class="summary-content-title-wrapper">
<div class="col-md-9"> <div class="col-md-9">
<div class="summary-content-poster hidden-xs hidden-sm"> <div class="summary-content-poster hidden-xs hidden-sm">
% if data['type'] == 'episode': <a href="http://app.plex.tv/web/app#!/server/${config['pms_identifier']}/details/%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="Plex/Web" title="View in Plex/Web">
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);"></div> % if data['type'] == 'episode':
% elif data['type'] == 'season': <div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);">
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="summary-poster-face-overlay">
% else: <span></span>
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div> </div>
% endif </div>
% else:
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);">
<div class="summary-poster-face-overlay">
<span></span>
</div>
</div>
% endif
</a>
</div> </div>
<div class="summary-content-title"> <div class="summary-content-title">
% if data['type'] == 'movie' or data['type'] == 'show': % if data['type'] == 'movie' or data['type'] == 'show':
@ -263,6 +271,24 @@ DOCUMENTATION :: END
</div> </div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal"> <div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div> </div>
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title" id="myModalLabel">Confirm Delete</h4>
</div>
<div class="modal-body" style="text-align: center;">
<p>Are you REALLY sure you want to delete <strong><span id="deleteCount"></span></strong> history item(s)?</p>
<p>This is permanent and cannot be undone!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-delete">Delete</button>
</div>
</div>
</div>
</div>
</div> </div>
% endif % endif
</div> </div>
@ -312,19 +338,43 @@ DOCUMENTATION :: END
} }
} }
history_table = $('#history_table').DataTable(history_table_options); history_table = $('#history_table').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] }); var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
$(colvis.button()).appendTo('div.colvis-button-bar'); $(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table', history_table); clearSearchButton('history_table', history_table);
$('#row-edit-mode').click(function() { $('#row-edit-mode').on('click', function() {
$('#row-edit-mode-alert').fadeIn(200);
if ($(this).hasClass('active')) { if ($(this).hasClass('active')) {
$('.delete-control').each(function() { if (history_to_delete.length > 0) {
$('#deleteCount').text(history_to_delete.length);
$('#confirm-modal').modal();
$('#confirm-modal').one('click', '#confirm-delete', function () {
for (var i = 0; i < history_to_delete.length; i++) {
$.ajax({
url: 'delete_history_rows',
data: { row_id: history_to_delete[i] },
async: true,
success: function (data) {
var msg = "History deleted";
showMsg(msg, false, true, 2000);
}
});
}
history_table.draw();
});
}
$('.delete-control').each(function () {
$(this).addClass('hidden'); $(this).addClass('hidden');
$('#row-edit-mode-alert').fadeOut(200);
}); });
} else { } else {
history_to_delete = [];
$('.delete-control').each(function() { $('.delete-control').each(function() {
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
$(this).removeClass('hidden'); $(this).removeClass('hidden');
}); });
} }
@ -386,6 +436,7 @@ DOCUMENTATION :: END
} }
}); });
}); });
$.ajax({ $.ajax({
url: 'get_show_children', url: 'get_show_children',
type: "GET", type: "GET",
@ -465,9 +516,7 @@ DOCUMENTATION :: END
<script> <script>
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY')); $("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true)); $("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
</script>
% endif
<script>
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 }); $('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
</script> </script>
% endif
</%def> </%def>

View file

@ -219,7 +219,11 @@ function getPlatformImagePath(platformName) {
return 'interfaces/default/images/platforms/playstation.png'; return 'interfaces/default/images/platforms/playstation.png';
} else if (platformName.indexOf("Mystery 5") > -1) { } else if (platformName.indexOf("Mystery 5") > -1) {
return 'interfaces/default/images/platforms/xbox.png'; return 'interfaces/default/images/platforms/xbox.png';
} else { } else if (platformName.indexOf("Windows") > -1) {
return 'interfaces/default/images/platforms/win8.png';
} else if (platformName.indexOf("Windows phone") > -1) {
return 'interfaces/default/images/platforms/wp.png';
} else {
return 'interfaces/default/images/platforms/default.png'; return 'interfaces/default/images/platforms/default.png';
} }
} }

View file

@ -55,6 +55,7 @@ def extract_plexwatch_xml(xml=None):
parent_title = helpers.get_xml_attr(a, 'parentTitle') parent_title = helpers.get_xml_attr(a, 'parentTitle')
studio = helpers.get_xml_attr(a, 'studio') studio = helpers.get_xml_attr(a, 'studio')
title = helpers.get_xml_attr(a, 'title') title = helpers.get_xml_attr(a, 'title')
tagline = helpers.get_xml_attr(a, 'tagline')
directors = [] directors = []
if a.getElementsByTagName('Director'): if a.getElementsByTagName('Director'):
@ -153,6 +154,7 @@ def extract_plexwatch_xml(xml=None):
'grandparent_title': grandparent_title, 'grandparent_title': grandparent_title,
'parent_title': parent_title, 'parent_title': parent_title,
'title': title, 'title': title,
'tagline': tagline,
'guid': guid, 'guid': guid,
'media_index': media_index, 'media_index': media_index,
'originally_available_at': originally_available_at, 'originally_available_at': originally_available_at,
@ -356,6 +358,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
'last_viewed_at': extracted_xml['last_viewed_at'], 'last_viewed_at': extracted_xml['last_viewed_at'],
'content_rating': row['content_rating'], 'content_rating': row['content_rating'],
'summary': row['summary'], 'summary': row['summary'],
'tagline': extracted_xml['tagline'],
'rating': extracted_xml['rating'], 'rating': extracted_xml['rating'],
'duration': extracted_xml['duration'], 'duration': extracted_xml['duration'],
'guid': extracted_xml['guid'], 'guid': extracted_xml['guid'],

View file

@ -1,2 +1,2 @@
PLEXPY_VERSION = "master" PLEXPY_VERSION = "master"
PLEXPY_RELEASE_VERSION = "1.1.7" PLEXPY_RELEASE_VERSION = "1.1.8"

View file

@ -762,6 +762,10 @@ class WebInterface(object):
def info(self, item_id=None, source=None, **kwargs): def info(self, item_id=None, source=None, **kwargs):
metadata = None metadata = None
config = {
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER
}
if source == 'history': if source == 'history':
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
metadata = data_factory.get_metadata_details(row_id=item_id) metadata = data_factory.get_metadata_details(row_id=item_id)
@ -772,7 +776,7 @@ class WebInterface(object):
metadata = result['metadata'] metadata = result['metadata']
if metadata: if metadata:
return serve_template(templatename="info.html", data=metadata, title="Info") return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
else: else:
logger.warn('Unable to retrieve data.') logger.warn('Unable to retrieve data.')
return serve_template(templatename="info.html", data=None, title="Info") return serve_template(templatename="info.html", data=None, title="Info")