Redo newsletter template using tables

This commit is contained in:
JonnyWong16 2018-03-24 00:02:31 -07:00
parent e1035a49fd
commit 3f7edc3635
6 changed files with 780 additions and 620 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -1,6 +1,7 @@
% if data: % if data:
<% <%
import plexpy import plexpy
from helpers import grouper
recently_added = data['recently_added'] recently_added = data['recently_added']
if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.NEWSLETTER_BASE_URL: if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.NEWSLETTER_BASE_URL:
@ -73,7 +74,7 @@
box-sizing: border-box; box-sizing: border-box;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
max-width: 1042px; max-width: 1037px;
padding: 10px; padding: 10px;
} }
@ -139,10 +140,8 @@
ul, ul,
ol { ol {
font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-family: 'Open Sans', Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 400; font-weight: 400;
margin: 0; margin: 0;
margin-bottom: 15px;
} }
p li, p li,
@ -245,6 +244,8 @@
.nowrap { .nowrap {
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
} }
.clear { .clear {
clear: both; clear: both;
@ -335,150 +336,135 @@
MEDIA CARDS MEDIA CARDS
------------------------------------- */ ------------------------------------- */
.card-instance { .card-instance {
float: left;
width: 500px;
margin: 3px;
border: 1px solid rgba(255,255,255,.1);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 12px; font-size: 12px;
overflow: hidden; overflow: hidden;
position: relative; padding: 3px;
width: 502px;
min-width: 502px;
max-width: 502px;
} }
.card-instance.movie, .card-instance.movie,
.card-instance.show { .card-instance.show {
height: 235px; height: 233px;
} }
.card-instance.album { .card-instance.album {
height: 160px; height: 158px;
}
.card-instance.odd {
float: none !important;
margin: 3px auto !important;
} }
.card-background { .card-background {
background-position: center; background-position: center;
background-size: cover; background-size: cover;
width: 100%; background-repeat: no-repeat;
height: 100%; background-clip: padding-box;
border: 1px solid rgba(255,255,255,.1);
} }
.card-poster-container { .card-poster-container {
width: 150px; width: 152px;
margin: 3px; min-width: 152px;
border: 1px solid rgba(255,255,255,.1);
float: left;
position: relative;
z-index: 1;
} }
.card-instance.movie .card-poster-container, .card-instance.movie .card-poster-container,
.card-instance.show .card-poster-container{ .card-instance.show .card-poster-container{
height: 225px; height: 227px;
} }
.card-instance.album .card-poster-container { .card-instance.album .card-poster-container {
height: 150px; height: 152px;
} }
.card-poster { .card-poster {
background-color: #3F4245; background-color: #3F4245;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
height: 100%; background-repeat: no-repeat;
width: 100%; background-clip: padding-box;
border: 1px solid rgba(255,255,255,.1);
} }
.card-poster-overlay { .card-poster-overlay {
background-repeat: no-repeat; display: block;
background-position: bottom right;
width: 100%;
height: 100%;
} }
.card-info-container { .card-info-container {
margin: 4px; padding-left: 4px;
width: 332px;
float: left;
position: relative;
z-index: 1;
} }
.card-instance.movie .card-info-container, .card-instance.movie .card-info-container,
.card-instance.show .card-info-container{ .card-instance.show .card-info-container{
height: 225px; height: 227px;
} }
.card-instance.album .card-info-container { .card-instance.album .card-info-container {
height: 150px; height: 152px;
} }
.card-info-container > div { .card-info-container > table {
padding: 5px; height: 100%;
text-overflow: ellipsis;
overflow: hidden;
} }
.card-info-title { .card-info-title {
border-bottom: 1px solid rgba(255, 255, 255, .1); border-bottom: 1px solid rgba(255, 255, 255, .1);
line-height: 20px; line-height: 1.2rem;
font-size: 15px; font-size: 0.9rem;
padding: 5px;
} }
.card-info-title a { .card-info-title a {
text-decoration: none; text-decoration: none;
color: #ffffff; color: #ffffff;
} }
.card-info-body > div { .card-info-body {
color: #ffffff; font-size: 0.75rem;
font-size: 12px; padding: 5px;
text-overflow: ellipsis; height: 100%;
overflow: hidden; }
.card-info-body > p {
max-width: 325px;
} }
.card-instance.movie .card-info-body, .card-instance.movie .card-info-body,
.card-instance.show .card-info-body { .card-instance.show .card-info-body {
min-height: 157px;
} }
.card-instance.album .card-info-body { .card-instance.album .card-info-body {
height: 82px;
min-height: 82px; min-height: 82px;
} }
.card-info-footer { .card-info-footer {
font-size: 10px; font-size: 0.6rem;
padding-top: 0px;
padding-right: 5px;
padding-bottom: 5px;
padding-left: 5px;
}
.card-info-footer .star-rating-container {
vertical-align: bottom;
padding-right: 5px;
} }
.card-info-footer .star-rating { .card-info-footer .star-rating {
width: 60px; font-size: 0.8rem;
font-size: 14px; line-height: 1rem;
line-height: 17px; width: 0.5rem;
float: right;
}
.star-rating-full {
color: #E5A00D;
direction: ltr;
padding: 0;
overflow: hidden;
float: left;
}
.star-rating-empty {
color: #aaaaaa;
direction: rtl;
padding: 0;
overflow: hidden;
float: left;
}
.star-rating span {
display: inline-block; display: inline-block;
text-align: center; }
width: 12px; .star-rating.full {
color: #E5A00D;
}
.star-rating.empty {
color: #aaaaaa;
} }
.badge { .badge {
display: inline-block; display: inline-block;
min-width: 10px; min-width: 10px;
padding: 3px 7px; padding: 3px 7px;
font-size: 11px; font-size: 11px;
font-style: normal;
line-height: 1; line-height: 1;
color: #fff;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
background-color: rgba(0, 0, 0, .25); background-color: rgba(0, 0, 0, .25);
border-radius: 2px; border-radius: 2px;
max-width: 75px;
text-overflow: ellipsis;
overflow: hidden;
} }
/* ------------------------------------- /* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */ ------------------------------------- */
@media only screen and (max-width: 620px) { @media only screen and (max-width: 1040px) {
.card-instance {
display: block !important;
margin: 0 auto;
}
table[class=body] .header { table[class=body] .header {
background-position: center !important; background-position: center !important;
} }
@ -510,11 +496,6 @@
font-size: 14px !important; font-size: 14px !important;
} }
table[class=body] .card-instance {
margin: 3px auto;
float: none;
}
table[class=body] .content { table[class=body] .content {
padding: 0 !important; padding: 0 !important;
} }
@ -573,12 +554,12 @@
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;"> <table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
<tr> <tr>
<td class="container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;display: block;max-width: 1042px;padding: 10px;width: 1042px;margin: 0 auto !important;"> <td class="container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;display: block;max-width: 1042px;padding: 10px;width: 1042px;margin: 0 auto !important;">
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 1042px;padding: 10px;"> <div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 1037px;padding: 10px;">
<!-- START CENTERED WHITE CONTAINER --> <!-- START CENTERED WHITE CONTAINER -->
<span class="preheader" style="color: transparent;display: none;height: 0;max-height: 0;max-width: 0;opacity: 0;overflow: hidden;mso-hide: all;visibility: hidden;width: 0;">Tautulli card-backbro - ${title}</span> <span class="preheader" style="color: transparent;display: none;height: 0;max-height: 0;max-width: 0;opacity: 0;overflow: hidden;mso-hide: all;visibility: hidden;width: 0;">Tautulli Newsletter - ${title}</span>
<table border="0" cellpadding="0" cellspacing="0" class="main" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background: #282A2D;border-radius: 3px;color: #ffffff;"> <table border="0" cellpadding="3" cellspacing="0" class="main" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background: #282A2D;border-radius: 3px;color: #ffffff;">
<!-- START MAIN CONTENT AREA --> <!-- START MAIN CONTENT AREA -->
<tr> <tr>
@ -588,9 +569,9 @@
<div class="dates" style="color: #aaaaaa;font-size: 20px;text-align: center;">${parameters['start_date']} - ${parameters['end_date']}</div> <div class="dates" style="color: #aaaaaa;font-size: 20px;text-align: center;">${parameters['start_date']} - ${parameters['end_date']}</div>
</td> </td>
</tr> </tr>
% if recently_added.get('movie'):
<tr> <tr>
<td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;"> <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
% if recently_added.get('movie'):
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> <div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div> <div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div>
@ -602,67 +583,106 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> </td>
% for movie in recently_added['movie']: </tr>
<% <tr>
if loop.index == len(recently_added['movie'])-1 and loop.index % 2 == 0: <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
clear = '<div style="clear: both;"></div>' <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
odd = 'odd' <tbody>
else: % for movie_a, movie_b in grouper(recently_added['movie'], 2):
clear = odd = '' <tr>
%> % for movie in (movie_a, movie_b):
${clear | n} % if movie:
<div class="card-instance movie ${odd}" style="float: left;width: 500px;margin: 3px;border: 1px solid rgba(255,255,255,.1);-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;font-size: 12px;overflow: hidden;position: relative;height: 235px;"> <td align="center" valign="top" class="card-instance movie" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;height: 233px;">
<div class="card-background" style="background-image: url(${(base_url + movie['art_hash']) if base_url else movie['art_url']});background-position: center;background-size: cover;width: 100%;height: 100%;"> <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + movie['art_hash']) if base_url else movie['art_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
<div class="card-poster-container" style="width: 150px;margin: 3px;border: 1px solid rgba(255,255,255,.1);float: left;position: relative;z-index: 1;height: 225px;"> <tbody>
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank" style="color: #3498db;text-decoration: underline;"> <tr>
<div class="card-poster" style="background-image: url(${(base_url + movie['thumb_hash']) if base_url else movie['poster_url']});background-color: #3F4245;background-position: center;background-size: cover;height: 100%;width: 100%;"> <td class="card-poster-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;width: 152px;min-width: 152px;height: 227px;">
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'});background-repeat: no-repeat;background-position: bottom right;width: 100%;height: 100%;"></div> <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + movie['thumb_hash']) if base_url else movie['poster_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-color: #3F4245;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
</div> <tbody>
</a> <tr>
</div> <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<div class="card-info-container" style="margin: 4px;width: 332px;float: left;position: relative;z-index: 1;height: 225px;"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank" style="color: #3498db;text-decoration: underline;">
<div class="card-info-title nowrap" style="white-space: nowrap;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 20px;font-size: 15px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-poster.png' if base_url else 'https://i.imgur.com/AeyPvJ4.png'}" width="150" height="225" style="border: none;-ms-interpolation-mode: bicubic;max-width: 100%;display: block;">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank" style="color: #ffffff;text-decoration: none;">${movie['title']}</a> </a>
</div> </td>
<div class="card-info-body" style="padding: 5px;text-overflow: ellipsis;overflow: hidden;min-height: 157px;"> </tr>
% if movie['tagline']: </tbody>
<div class="nowrap mb5" style="margin-bottom: 5px;white-space: nowrap;color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> </table>
<em>${movie['tagline']}</em> </td>
</div> <td class="card-info-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;padding-left: 4px;height: 227px;">
% endif <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;height: 100%;">
<div style="color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> <tbody>
${movie['summary'][:450] + (movie['summary'][450:] and '...')} <tr>
</div> <td class="card-info-title nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.9rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 1.2rem;padding: 5px;">
</div> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank" style="color: #ffffff;text-decoration: none;">${movie['title']}</a>
<div class="card-info-footer nowrap" style="white-space: nowrap;font-size: 10px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> </td>
% if movie['year']: </tr>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${movie['year']}</span> <tr>
% endif <td class="card-info-body" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.75rem;vertical-align: top;padding: 5px;height: 100%;">
% if movie['content_rating']: % if movie['tagline']:
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${movie['content_rating']}</span> <p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;">
% endif <em>${movie['tagline']}</em>
% if movie['duration']: </p>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${int(int(movie['duration'])/60000)} mins</span> % endif
% endif <p style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;max-width: 325px;">
% if movie['rating']: ${movie['summary'][:450] + (movie['summary'][450:] and '...')}
<span class="star-rating" title="${int(float(movie['rating'])/0.1)}%" style="width: 60px;font-size: 14px;line-height: 17px;float: right;"> </p>
<div class="star-rating-full nowrap" style="width: ${float(movie['rating'])/0.1}%;white-space: nowrap;color: #E5A00D;direction: ltr;padding: 0;overflow: hidden;float: left;"> </td>
<span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span> </tr>
</div> <tr>
<div class="star-rating-empty" style="width: ${100-float(movie['rating'])/0.1}%;color: #aaaaaa;direction: rtl;padding: 0;overflow: hidden;float: left;"> <td class="card-info-footer nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.6rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;padding-top: 0px;padding-right: 5px;padding-bottom: 5px;padding-left: 5px;">
<span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
</div> <tbody>
</span> <tr>
% endif <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
</div> % if movie['year']:
</div> <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${movie['year']}</span>
</div> % endif
</div> % if movie['content_rating']:
% endfor <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${movie['content_rating']}</span>
</div> % endif
% endif % if movie['duration']:
% if recently_added.get('show'): <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${int(int(movie['duration'])/60000)} mins</span>
% endif
</td>
% if movie['rating']:
<% rating = int(round(float(movie['rating']) / 2)) %>
<td class="star-rating-container" title="${int(float(movie['rating'])/0.1)}%" align="right" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: bottom;padding-right: 5px;">
% for _ in range(rating):
<span class="star-rating full" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #E5A00D;">&#9733;</span>
% endfor
% for _ in range(5-rating):
<span class="star-rating empty" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #aaaaaa;">&#9734;</span>
% endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
% if recently_added.get('show'):
<tr>
<td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> <div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div> <div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div>
@ -676,101 +696,129 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
% for show in recently_added['show']: <tbody>
<% % for show_a, show_b in grouper(recently_added['show'], 2):
if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: <tr>
link_rating_key = show['season'][0]['episode'][0]['rating_key'] % for show in (show_a, show_b):
link_title = show['title'] + " - " + show['season'][0]['episode'][0]['title'] % if show:
else: <td align="center" valign="top" class="card-instance show" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;height: 233px;">
link_rating_key = show['rating_key'] <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + show['art_hash']) if base_url else show['art_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
link_title = show['title'] <tbody>
<tr>
if loop.index == len(recently_added['show'])-1 and loop.index % 2 == 0: <td class="card-poster-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;width: 152px;min-width: 152px;height: 227px;">
clear = '<div style="clear: both;"></div>' <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + show['thumb_hash']) if base_url else show['poster_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-color: #3F4245;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
odd = 'odd' <tbody>
else: <tr>
clear = odd = '' <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
%> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${show['rating_key']}" title="${show['title']}" target="_blank" style="color: #3498db;text-decoration: underline;">
${clear | n} <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-poster.png' if base_url else 'https://i.imgur.com/AeyPvJ4.png'}" width="150" height="225" style="border: none;-ms-interpolation-mode: bicubic;max-width: 100%;display: block;">
<div class="card-instance show ${odd}" style="float: left;width: 500px;margin: 3px;border: 1px solid rgba(255,255,255,.1);-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;font-size: 12px;overflow: hidden;position: relative;height: 235px;"> </a>
<div class="card-background" style="background-image: url(${(base_url + show['art_hash']) if base_url else show['art_url']});background-position: center;background-size: cover;width: 100%;height: 100%;"> </td>
<div class="card-poster-container" style="width: 150px;margin: 3px;border: 1px solid rgba(255,255,255,.1);float: left;position: relative;z-index: 1;height: 225px;"> </tr>
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${link_rating_key}" title="${link_title}" target="_blank" style="color: #3498db;text-decoration: underline;"> </tbody>
<div class="card-poster" style="background-image: url(${(base_url + show['thumb_hash']) if base_url else show['poster_url']});background-color: #3F4245;background-position: center;background-size: cover;height: 100%;width: 100%;"> </table>
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'});background-repeat: no-repeat;background-position: bottom right;width: 100%;height: 100%;"></div> </td>
</div> <td class="card-info-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;padding-left: 4px;height: 227px;">
</a> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;height: 100%;">
</div> <tbody>
<div class="card-info-container" style="margin: 4px;width: 332px;float: left;position: relative;z-index: 1;height: 225px;"> <tr>
<div class="card-info-title nowrap" style="white-space: nowrap;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 20px;font-size: 15px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> <td class="card-info-title nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.9rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 1.2rem;padding: 5px;">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${link_rating_key}" title="${link_title}" target="_blank" style="color: #ffffff;text-decoration: none;">${show['title']}</a> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${show['rating_key']}" title="${show['title']}" target="_blank" style="color: #ffffff;text-decoration: none;">${show['title']}</a>
</div> </td>
<div class="card-info-body" style="padding: 5px;text-overflow: ellipsis;overflow: hidden;min-height: 157px;"> </tr>
<div class="nowrap mb5" style="margin-bottom: 5px;white-space: nowrap;color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> <tr>
% if show['season_count'] > 1: <td class="card-info-body" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.75rem;vertical-align: top;padding: 5px;height: 100%;">
<em>${show['season_count']} seasons /</em> <p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;">
% endif % if show['season_count'] > 1:
<% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> <em>${show['season_count']} seasons /</em>
<em>${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''}</em> % endif
</div> <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %>
<div class="nowrap mb5" style="margin-bottom: 5px;white-space: nowrap;color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> <em>${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''}</em>
% for i, season in enumerate(show['season'][:8]): </p>
Season ${season['media_index']} &middot; <p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;">
% if season['episode_count'] == 1: % for i, season in enumerate(show['season'][:8]):
Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} Season ${season['media_index']} &middot;
% else: % if season['episode_count'] == 1:
Episodes ${season['episode_range']} Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']}
% endif % else:
% if i < min(show['season_count'], 7): Episodes ${season['episode_range']}
<br> % endif
% elif i == 7 and show['season_count'] > 8: % if i < min(show['season_count'], 7):
...plus ${show['season_count'] - 8} more seasons! <br>
% endif % elif i == 7 and show['season_count'] > 8:
% endfor ...plus ${show['season_count'] - 8} more seasons!
</div> % endif
<div style="color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> % endfor
% if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: </p>
${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} <p style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;max-width: 325px;">
% else: % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1:
<% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')}
% if length: % else:
${show['summary'][:length] + (show['summary'][length:] and '...')} <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %>
% endif % if length:
% endif ${show['summary'][:length] + (show['summary'][length:] and '...')}
</div> % endif
</div> % endif
<div class="card-info-footer nowrap" style="white-space: nowrap;font-size: 10px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> </p>
% if show['studio']: </td>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${show['studio']}</span> </tr>
% endif <tr>
% if show['year']: <td class="card-info-footer nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.6rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;padding-top: 0px;padding-right: 5px;padding-bottom: 5px;padding-left: 5px;">
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${show['year']}</span> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
% endif <tbody>
% if show['content_rating']: <tr>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${show['content_rating']}</span> <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
% endif % if show['studio']:
% if show['duration']: <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${show['studio']}</span>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${int(int(show['duration'])/60000)} mins</span> % endif
% endif % if show['year']:
% if show['rating']: <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${show['year']}</span>
<span class="star-rating" title="${int(float(show['rating'])/0.1)}%" style="width: 60px;font-size: 14px;line-height: 17px;float: right;"> % endif
<div class="star-rating-full nowrap" style="width: ${float(show['rating'])/0.1}%;white-space: nowrap;color: #E5A00D;direction: ltr;padding: 0;overflow: hidden;float: left;"> % if show['content_rating']:
<span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span> <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${show['content_rating']}</span>
</div> % endif
<div class="star-rating-empty" style="width: ${100-float(show['rating'])/0.1}%;color: #aaaaaa;direction: rtl;padding: 0;overflow: hidden;float: left;"> % if show['duration']:
<span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span> <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${int(int(show['duration'])/60000)} mins</span>
</div> % endif
</span> </td>
% endif % if show['rating']:
</div> <% rating = int(round(float(show['rating']) / 2)) %>
</div> <td class="star-rating-container" title="${int(float(show['rating'])/0.1)}%" align="right" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: bottom;padding-right: 5px;">
</div> % for _ in range(rating):
</div> <span class="star-rating full" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #E5A00D;">&#9733;</span>
% endfor % endfor
</div> % for _ in range(5-rating):
% endif <span class="star-rating empty" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #aaaaaa;">&#9734;</span>
% if recently_added.get('artist'): % endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
% if recently_added.get('artist'):
<tr>
<td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> <div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div> <div class="sub-header-bar" style="width: 200px;border-top: 1px solid #E5A00D;margin-top: 15px;margin-bottom: 25px;margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;"></div>
@ -784,71 +832,100 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper" style="box-sizing: border-box;padding: 5px;overflow: auto;"> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
<% album_count = 0 %> <tbody>
% for artist in recently_added['artist']: % for album_a, album_b in grouper([a for artist in recently_added['artist'] for a in artist['album']], 2):
% for album in artist['album']: <tr>
<% % for album in (album_a, album_b):
album_count += 1 % if album:
<td align="center" valign="top" class="card-instance album" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;height: 158px;">
if album_count == total_albums and album_count % 2 == 1: <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + album['art_hash']) if base_url else album['art_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
clear = '<div style="clear: both;"></div>' <tbody>
odd = 'odd' <tr>
else: <td class="card-poster-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;width: 152px;min-width: 152px;height: 152px;">
clear = odd = '' <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + album['thumb_hash']) if base_url else album['poster_url']});border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;background-color: #3F4245;background-position: center;background-size: cover;background-repeat: no-repeat;background-clip: padding-box;border: 1px solid rgba(255,255,255,.1);">
%> <tbody>
${clear | n} <tr>
<div class="card-instance album ${odd}" style="float: left;width: 500px;margin: 3px;border: 1px solid rgba(255,255,255,.1);-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;font-size: 12px;overflow: hidden;position: relative;height: 160px;"> <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<div class="card-background" style="background-image: url(${(base_url + album['art_hash']) if base_url else album['art_url']});background-position: center;background-size: cover;width: 100%;height: 100%;"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank" style="color: #3498db;text-decoration: underline;">
<div class="card-poster-container" style="width: 150px;margin: 3px;border: 1px solid rgba(255,255,255,.1);float: left;position: relative;z-index: 1;height: 150px;"> <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-cover.png' if base_url else 'https://i.imgur.com/ObC1NeY.png'}" width="150" height="150" style="border: none;-ms-interpolation-mode: bicubic;max-width: 100%;display: block;">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank" style="color: #3498db;text-decoration: underline;"> </a>
<div class="card-poster" style="background-image: url(${(base_url + album['thumb_hash']) if base_url else album['poster_url']});background-color: #3F4245;background-position: center;background-size: cover;height: 100%;width: 100%;"> </td>
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'});background-repeat: no-repeat;background-position: bottom right;width: 100%;height: 100%;"></div> </tr>
</div> </tbody>
</a> </table>
</div> </td>
<div class="card-info-container" style="margin: 4px;width: 332px;float: left;position: relative;z-index: 1;height: 150px;"> <td class="card-info-container" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;padding-left: 4px;height: 152px;">
<div class="card-info-title nowrap" style="white-space: nowrap;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 20px;font-size: 15px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;height: 100%;">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank" style="color: #ffffff;text-decoration: none;">${album['title']}</a> <tbody>
</div> <tr>
<div class="card-info-body" style="padding: 5px;text-overflow: ellipsis;overflow: hidden;min-height: 82px;"> <td class="card-info-title nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.9rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;border-bottom: 1px solid rgba(255, 255, 255, .1);line-height: 1.2rem;padding: 5px;">
<div class="nowrap mb5" style="margin-bottom: 5px;white-space: nowrap;color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank" style="color: #ffffff;text-decoration: none;">${album['title']}</a>
<em>${artist['title']} &middot; ${album['track_count']} track${'s' if album['track_count'] > 1 else ''}</em> </td>
</div> </tr>
% if artist['title'].lower() != 'various artists': <tr>
<div style="color: #ffffff;font-size: 12px;text-overflow: ellipsis;overflow: hidden;"> <td class="card-info-body" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.75rem;vertical-align: top;padding: 5px;height: 82px;min-height: 82px;">
${album['summary'][:200] + (album['summary'][200:] and '...')} <p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;">
</div> <em>${album['parent_title']} &middot; ${album['track_count']} track${'s' if album['track_count'] > 1 else ''}</em>
% endif </p>
</div> % if artist['title'].lower() != 'various artists':
<div class="card-info-footer nowrap" style="white-space: nowrap;font-size: 10px;padding: 5px;text-overflow: ellipsis;overflow: hidden;"> <p style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;max-width: 325px;">
% if album['year']: ${album['summary'][:200] + (album['summary'][200:] and '...')}
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${album['year']}</span> </p>
% endif % endif
% if album['genres']: </td>
% for genre in album['genres'][:2]: </tr>
<span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;font-style: normal;line-height: 1;color: #fff;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;">${genre}</span> <tr>
% endfor <td class="card-info-footer nowrap" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 0.6rem;vertical-align: top;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;padding-top: 0px;padding-right: 5px;padding-bottom: 5px;padding-left: 5px;">
% endif <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;">
% if album['rating']: <tbody>
<span class="star-rating" title="${int(float(album['rating'])/0.1)}%" style="width: 60px;font-size: 14px;line-height: 17px;float: right;"> <tr>
<div class="star-rating-full nowrap" style="width: ${float(album['rating'])/0.1}%;white-space: nowrap;color: #E5A00D;direction: ltr;padding: 0;overflow: hidden;float: left;"> <td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9733;</span> % if album['year']:
</div> <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${album['year']}</span>
<div class="star-rating-empty" style="width: ${100-float(album['rating'])/0.1}%;color: #aaaaaa;direction: rtl;padding: 0;overflow: hidden;float: left;"> % endif
<span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span><span style="display: inline-block;text-align: center;width: 12px;">&#9734;</span> % if album['genres']:
</div> % for genre in album['genres'][:2]:
</span> <span class="badge" style="display: inline-block;min-width: 10px;padding: 3px 7px;font-size: 11px;line-height: 1;text-align: center;white-space: nowrap;vertical-align: middle;background-color: rgba(0, 0, 0, .25);border-radius: 2px;max-width: 75px;text-overflow: ellipsis;overflow: hidden;">${genre}</span>
% endif % endfor
</div> % endif
</div> </td>
</div> % if album['rating']:
</div> <% rating = int(round(float(album['rating']) / 2)) %>
% endfor <td class="star-rating-container" title="${int(float(album['rating'])/0.1)}%" align="right" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: bottom;padding-right: 5px;">
% endfor % for _ in range(rating):
</div> <span class="star-rating full" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #E5A00D;">&#9733;</span>
% endif % endfor
% for _ in range(5-rating):
<span class="star-rating empty" style="font-size: 0.8rem;line-height: 1rem;width: 0.5rem;display: inline-block;color: #aaaaaa;">&#9734;</span>
% endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 12px;vertical-align: top;overflow: hidden;padding: 3px;width: 502px;min-width: 502px;max-width: 502px;"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
<tr>
<td style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-size: 14px;vertical-align: top;">
<!-- START FOOTER --> <!-- START FOOTER -->
<div class="footer" style="clear: both;margin-top: 10px;text-align: center;width: 100%;font-size: 12px;"> <div class="footer" style="clear: both;margin-top: 10px;text-align: center;width: 100%;font-size: 12px;">
<div class="footer-bar" style="margin-left: auto;margin-right: auto;width: 200px;border-top: 1px solid #E5A00D;margin-top: 25px;"></div> <div class="footer-bar" style="margin-left: auto;margin-right: auto;width: 200px;border-top: 1px solid #E5A00D;margin-top: 25px;"></div>
@ -857,7 +934,6 @@
</div> </div>
</div> </div>
<!-- END FOOTER --> <!-- END FOOTER -->
</td> </td>
</tr> </tr>

View file

@ -1,6 +1,7 @@
% if data: % if data:
<% <%
import plexpy import plexpy
from helpers import grouper
recently_added = data['recently_added'] recently_added = data['recently_added']
if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.NEWSLETTER_BASE_URL: if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.NEWSLETTER_BASE_URL:
@ -73,7 +74,7 @@
box-sizing: border-box; box-sizing: border-box;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
max-width: 1042px; max-width: 1037px;
padding: 10px; padding: 10px;
} }
@ -139,10 +140,8 @@
ul, ul,
ol { ol {
font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-family: 'Open Sans', Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 400; font-weight: 400;
margin: 0; margin: 0;
margin-bottom: 15px;
} }
p li, p li,
@ -245,6 +244,8 @@
.nowrap { .nowrap {
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
} }
.clear { .clear {
clear: both; clear: both;
@ -335,150 +336,135 @@
MEDIA CARDS MEDIA CARDS
------------------------------------- */ ------------------------------------- */
.card-instance { .card-instance {
float: left;
width: 500px;
margin: 3px;
border: 1px solid rgba(255,255,255,.1);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 12px; font-size: 12px;
overflow: hidden; overflow: hidden;
position: relative; padding: 3px;
width: 502px;
min-width: 502px;
max-width: 502px;
} }
.card-instance.movie, .card-instance.movie,
.card-instance.show { .card-instance.show {
height: 235px; height: 233px;
} }
.card-instance.album { .card-instance.album {
height: 160px; height: 158px;
}
.card-instance.odd {
float: none !important;
margin: 3px auto !important;
} }
.card-background { .card-background {
background-position: center; background-position: center;
background-size: cover; background-size: cover;
width: 100%; background-repeat: no-repeat;
height: 100%; background-clip: padding-box;
border: 1px solid rgba(255,255,255,.1);
} }
.card-poster-container { .card-poster-container {
width: 150px; width: 152px;
margin: 3px; min-width: 152px;
border: 1px solid rgba(255,255,255,.1);
float: left;
position: relative;
z-index: 1;
} }
.card-instance.movie .card-poster-container, .card-instance.movie .card-poster-container,
.card-instance.show .card-poster-container{ .card-instance.show .card-poster-container{
height: 225px; height: 227px;
} }
.card-instance.album .card-poster-container { .card-instance.album .card-poster-container {
height: 150px; height: 152px;
} }
.card-poster { .card-poster {
background-color: #3F4245; background-color: #3F4245;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
height: 100%; background-repeat: no-repeat;
width: 100%; background-clip: padding-box;
border: 1px solid rgba(255,255,255,.1);
} }
.card-poster-overlay { .card-poster-overlay {
background-repeat: no-repeat; display: block;
background-position: bottom right;
width: 100%;
height: 100%;
} }
.card-info-container { .card-info-container {
margin: 4px; padding-left: 4px;
width: 332px;
float: left;
position: relative;
z-index: 1;
} }
.card-instance.movie .card-info-container, .card-instance.movie .card-info-container,
.card-instance.show .card-info-container{ .card-instance.show .card-info-container{
height: 225px; height: 227px;
} }
.card-instance.album .card-info-container { .card-instance.album .card-info-container {
height: 150px; height: 152px;
} }
.card-info-container > div { .card-info-container > table {
padding: 5px; height: 100%;
text-overflow: ellipsis;
overflow: hidden;
} }
.card-info-title { .card-info-title {
border-bottom: 1px solid rgba(255, 255, 255, .1); border-bottom: 1px solid rgba(255, 255, 255, .1);
line-height: 20px; line-height: 1.2rem;
font-size: 15px; font-size: 0.9rem;
padding: 5px;
} }
.card-info-title a { .card-info-title a {
text-decoration: none; text-decoration: none;
color: #ffffff; color: #ffffff;
} }
.card-info-body > div { .card-info-body {
color: #ffffff; font-size: 0.75rem;
font-size: 12px; padding: 5px;
text-overflow: ellipsis; height: 100%;
overflow: hidden; }
.card-info-body > p {
max-width: 325px;
} }
.card-instance.movie .card-info-body, .card-instance.movie .card-info-body,
.card-instance.show .card-info-body { .card-instance.show .card-info-body {
min-height: 157px;
} }
.card-instance.album .card-info-body { .card-instance.album .card-info-body {
height: 82px;
min-height: 82px; min-height: 82px;
} }
.card-info-footer { .card-info-footer {
font-size: 10px; font-size: 0.6rem;
padding-top: 0px;
padding-right: 5px;
padding-bottom: 5px;
padding-left: 5px;
}
.card-info-footer .star-rating-container {
vertical-align: bottom;
padding-right: 5px;
} }
.card-info-footer .star-rating { .card-info-footer .star-rating {
width: 60px; font-size: 0.8rem;
font-size: 14px; line-height: 1rem;
line-height: 17px; width: 0.5rem;
float: right;
}
.star-rating-full {
color: #E5A00D;
direction: ltr;
padding: 0;
overflow: hidden;
float: left;
}
.star-rating-empty {
color: #aaaaaa;
direction: rtl;
padding: 0;
overflow: hidden;
float: left;
}
.star-rating span {
display: inline-block; display: inline-block;
text-align: center; }
width: 12px; .star-rating.full {
color: #E5A00D;
}
.star-rating.empty {
color: #aaaaaa;
} }
.badge { .badge {
display: inline-block; display: inline-block;
min-width: 10px; min-width: 10px;
padding: 3px 7px; padding: 3px 7px;
font-size: 11px; font-size: 11px;
font-style: normal;
line-height: 1; line-height: 1;
color: #fff;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
background-color: rgba(0, 0, 0, .25); background-color: rgba(0, 0, 0, .25);
border-radius: 2px; border-radius: 2px;
max-width: 75px;
text-overflow: ellipsis;
overflow: hidden;
} }
/* ------------------------------------- /* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */ ------------------------------------- */
@media only screen and (max-width: 620px) { @media only screen and (max-width: 1040px) {
.card-instance {
display: block !important;
margin: 0 auto;
}
table[class=body] .header { table[class=body] .header {
background-position: center !important; background-position: center !important;
} }
@ -510,11 +496,6 @@
font-size: 14px !important; font-size: 14px !important;
} }
table[class=body] .card-instance {
margin: 3px auto;
float: none;
}
table[class=body] .content { table[class=body] .content {
padding: 0 !important; padding: 0 !important;
} }
@ -576,9 +557,9 @@
<div class="content"> <div class="content">
<!-- START CENTERED WHITE CONTAINER --> <!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">Tautulli card-backbro - ${title}</span> <span class="preheader">Tautulli Newsletter - ${title}</span>
<table border="0" cellpadding="0" cellspacing="0" class="main"> <table border="0" cellpadding="3" cellspacing="0" class="main">
<!-- START MAIN CONTENT AREA --> <!-- START MAIN CONTENT AREA -->
<tr> <tr>
@ -588,9 +569,9 @@
<div class="dates">${parameters['start_date']} - ${parameters['end_date']}</div> <div class="dates">${parameters['start_date']} - ${parameters['end_date']}</div>
</td> </td>
</tr> </tr>
% if recently_added.get('movie'):
<tr> <tr>
<td> <td>
% if recently_added.get('movie'):
<div class="wrapper"> <div class="wrapper">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar"></div> <div class="sub-header-bar"></div>
@ -602,67 +583,106 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper"> </td>
% for movie in recently_added['movie']: </tr>
<% <tr>
if loop.index == len(recently_added['movie'])-1 and loop.index % 2 == 0: <td>
clear = '<div style="clear: both;"></div>' <table border="0" cellpadding="0" cellspacing="0">
odd = 'odd' <tbody>
else: % for movie_a, movie_b in grouper(recently_added['movie'], 2):
clear = odd = '' <tr>
%> % for movie in (movie_a, movie_b):
${clear | n} % if movie:
<div class="card-instance movie ${odd}"> <td align="center" valign="top" class="card-instance movie">
<div class="card-background" style="background-image: url(${(base_url + movie['art_hash']) if base_url else movie['art_url']});"> <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + movie['art_hash']) if base_url else movie['art_url']});">
<div class="card-poster-container"> <tbody>
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank"> <tr>
<div class="card-poster" style="background-image: url(${(base_url + movie['thumb_hash']) if base_url else movie['poster_url']})"> <td class="card-poster-container">
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'})"></div> <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + movie['thumb_hash']) if base_url else movie['poster_url']})">
</div> <tbody>
</a> <tr>
</div> <td>
<div class="card-info-container"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank">
<div class="card-info-title nowrap"> <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-poster.png' if base_url else 'https://i.imgur.com/AeyPvJ4.png'}" width="150" height="225">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank">${movie['title']}</a> </a>
</div> </td>
<div class="card-info-body"> </tr>
% if movie['tagline']: </tbody>
<div class="nowrap mb5"> </table>
<em>${movie['tagline']}</em> </td>
</div> <td class="card-info-container">
% endif <table border="0" cellpadding="0" cellspacing="0">
<div> <tbody>
${movie['summary'][:450] + (movie['summary'][450:] and '...')} <tr>
</div> <td class="card-info-title nowrap">
</div> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${movie['rating_key']}" title="${movie['title']}" target="_blank">${movie['title']}</a>
<div class="card-info-footer nowrap"> </td>
% if movie['year']: </tr>
<span class="badge">${movie['year']}</span> <tr>
% endif <td class="card-info-body">
% if movie['content_rating']: % if movie['tagline']:
<span class="badge">${movie['content_rating']}</span> <p class="nowrap mb5">
% endif <em>${movie['tagline']}</em>
% if movie['duration']: </p>
<span class="badge">${int(int(movie['duration'])/60000)} mins</span> % endif
% endif <p>
% if movie['rating']: ${movie['summary'][:450] + (movie['summary'][450:] and '...')}
<span class="star-rating" title="${int(float(movie['rating'])/0.1)}%"> </p>
<div class="star-rating-full nowrap" style="width: ${float(movie['rating'])/0.1}%"> </td>
<span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span> </tr>
</div> <tr>
<div class="star-rating-empty" style="width: ${100-float(movie['rating'])/0.1}%"> <td class="card-info-footer nowrap">
<span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span> <table border="0" cellpadding="0" cellspacing="0">
</div> <tbody>
</span> <tr>
% endif <td>
</div> % if movie['year']:
</div> <span class="badge">${movie['year']}</span>
</div> % endif
</div> % if movie['content_rating']:
% endfor <span class="badge">${movie['content_rating']}</span>
</div> % endif
% endif % if movie['duration']:
% if recently_added.get('show'): <span class="badge">${int(int(movie['duration'])/60000)} mins</span>
% endif
</td>
% if movie['rating']:
<% rating = int(round(float(movie['rating']) / 2)) %>
<td class="star-rating-container" title="${int(float(movie['rating'])/0.1)}%" align="right">
% for _ in range(rating):
<span class="star-rating full">&#9733;</span>
% endfor
% for _ in range(5-rating):
<span class="star-rating empty">&#9734;</span>
% endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
% if recently_added.get('show'):
<tr>
<td>
<div class="wrapper"> <div class="wrapper">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar"></div> <div class="sub-header-bar"></div>
@ -676,101 +696,129 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper"> <table border="0" cellpadding="0" cellspacing="0">
% for show in recently_added['show']: <tbody>
<% % for show_a, show_b in grouper(recently_added['show'], 2):
if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: <tr>
link_rating_key = show['season'][0]['episode'][0]['rating_key'] % for show in (show_a, show_b):
link_title = show['title'] + " - " + show['season'][0]['episode'][0]['title'] % if show:
else: <td align="center" valign="top" class="card-instance show">
link_rating_key = show['rating_key'] <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + show['art_hash']) if base_url else show['art_url']});">
link_title = show['title'] <tbody>
<tr>
if loop.index == len(recently_added['show'])-1 and loop.index % 2 == 0: <td class="card-poster-container">
clear = '<div style="clear: both;"></div>' <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + show['thumb_hash']) if base_url else show['poster_url']})">
odd = 'odd' <tbody>
else: <tr>
clear = odd = '' <td>
%> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${show['rating_key']}" title="${show['title']}" target="_blank">
${clear | n} <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-poster.png' if base_url else 'https://i.imgur.com/AeyPvJ4.png'}" width="150" height="225">
<div class="card-instance show ${odd}"> </a>
<div class="card-background" style="background-image: url(${(base_url + show['art_hash']) if base_url else show['art_url']});"> </td>
<div class="card-poster-container"> </tr>
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${link_rating_key}" title="${link_title}" target="_blank"> </tbody>
<div class="card-poster" style="background-image: url(${(base_url + show['thumb_hash']) if base_url else show['poster_url']});"> </table>
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'})"></div> </td>
</div> <td class="card-info-container">
</a> <table border="0" cellpadding="0" cellspacing="0">
</div> <tbody>
<div class="card-info-container"> <tr>
<div class="card-info-title nowrap"> <td class="card-info-title nowrap">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${link_rating_key}" title="${link_title}" target="_blank">${show['title']}</a> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${show['rating_key']}" title="${show['title']}" target="_blank">${show['title']}</a>
</div> </td>
<div class="card-info-body"> </tr>
<div class="nowrap mb5"> <tr>
% if show['season_count'] > 1: <td class="card-info-body">
<em>${show['season_count']} seasons /</em> <p class="nowrap mb5">
% endif % if show['season_count'] > 1:
<% total_show_episodes = sum(s['episode_count'] for s in show['season']) %> <em>${show['season_count']} seasons /</em>
<em>${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''}</em> % endif
</div> <% total_show_episodes = sum(s['episode_count'] for s in show['season']) %>
<div class="nowrap mb5"> <em>${total_show_episodes} episode${'s' if total_show_episodes > 1 else ''}</em>
% for i, season in enumerate(show['season'][:8]): </p>
Season ${season['media_index']} &middot; <p class="nowrap mb5">
% if season['episode_count'] == 1: % for i, season in enumerate(show['season'][:8]):
Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} Season ${season['media_index']} &middot;
% else: % if season['episode_count'] == 1:
Episodes ${season['episode_range']} Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']}
% endif % else:
% if i < min(show['season_count'], 7): Episodes ${season['episode_range']}
<br> % endif
% elif i == 7 and show['season_count'] > 8: % if i < min(show['season_count'], 7):
...plus ${show['season_count'] - 8} more seasons! <br>
% endif % elif i == 7 and show['season_count'] > 8:
% endfor ...plus ${show['season_count'] - 8} more seasons!
</div> % endif
<div> % endfor
% if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1: </p>
${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')} <p>
% else: % if show['season_count'] == 1 and show['season'][0]['episode_count'] == 1:
<% length = max(0, 350 - 50 * (show['season_count'] - 1)) %> ${show['season'][0]['episode'][0]['summary'][:350] + (show['season'][0]['episode'][0]['summary'][350:] and '...')}
% if length: % else:
${show['summary'][:length] + (show['summary'][length:] and '...')} <% length = max(0, 350 - 50 * (show['season_count'] - 1)) %>
% endif % if length:
% endif ${show['summary'][:length] + (show['summary'][length:] and '...')}
</div> % endif
</div> % endif
<div class="card-info-footer nowrap"> </p>
% if show['studio']: </td>
<span class="badge">${show['studio']}</span> </tr>
% endif <tr>
% if show['year']: <td class="card-info-footer nowrap">
<span class="badge">${show['year']}</span> <table border="0" cellpadding="0" cellspacing="0">
% endif <tbody>
% if show['content_rating']: <tr>
<span class="badge">${show['content_rating']}</span> <td>
% endif % if show['studio']:
% if show['duration']: <span class="badge">${show['studio']}</span>
<span class="badge">${int(int(show['duration'])/60000)} mins</span> % endif
% endif % if show['year']:
% if show['rating']: <span class="badge">${show['year']}</span>
<span class="star-rating" title="${int(float(show['rating'])/0.1)}%"> % endif
<div class="star-rating-full nowrap" style="width: ${float(show['rating'])/0.1}%"> % if show['content_rating']:
<span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span> <span class="badge">${show['content_rating']}</span>
</div> % endif
<div class="star-rating-empty" style="width: ${100-float(show['rating'])/0.1}%"> % if show['duration']:
<span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span> <span class="badge">${int(int(show['duration'])/60000)} mins</span>
</div> % endif
</span> </td>
% endif % if show['rating']:
</div> <% rating = int(round(float(show['rating']) / 2)) %>
</div> <td class="star-rating-container" title="${int(float(show['rating'])/0.1)}%" align="right">
</div> % for _ in range(rating):
</div> <span class="star-rating full">&#9733;</span>
% endfor % endfor
</div> % for _ in range(5-rating):
% endif <span class="star-rating empty">&#9734;</span>
% if recently_added.get('artist'): % endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
% if recently_added.get('artist'):
<tr>
<td>
<div class="wrapper"> <div class="wrapper">
<div class="sub-header"> <div class="sub-header">
<div class="sub-header-bar"></div> <div class="sub-header-bar"></div>
@ -784,71 +832,100 @@
</div> </div>
</div> </div>
</div> </div>
<div class="wrapper"> <table border="0" cellpadding="0" cellspacing="0">
<% album_count = 0 %> <tbody>
% for artist in recently_added['artist']: % for album_a, album_b in grouper([a for artist in recently_added['artist'] for a in artist['album']], 2):
% for album in artist['album']: <tr>
<% % for album in (album_a, album_b):
album_count += 1 % if album:
<td align="center" valign="top" class="card-instance album">
if album_count == total_albums and album_count % 2 == 1: <table border="0" cellpadding="0" cellspacing="3" width="100%" class="card-background" style="background-image: url(${(base_url + album['art_hash']) if base_url else album['art_url']});">
clear = '<div style="clear: both;"></div>' <tbody>
odd = 'odd' <tr>
else: <td class="card-poster-container">
clear = odd = '' <table border="0" cellpadding="0" cellspacing="0" class="card-poster" style="background-image: url(${(base_url + album['thumb_hash']) if base_url else album['poster_url']})">
%> <tbody>
${clear | n} <tr>
<div class="card-instance album ${odd}"> <td>
<div class="card-background" style="background-image: url(${(base_url + album['art_hash']) if base_url else album['art_url']});"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank">
<div class="card-poster-container"> <img class="card-poster-overlay" src="${base_url + 'images/newsletter/view-on-plex-cover.png' if base_url else 'https://i.imgur.com/ObC1NeY.png'}" width="150" height="150">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank"> </a>
<div class="card-poster" style="background-image: url(${(base_url + album['thumb_hash']) if base_url else album['poster_url']});"> </td>
<div class="card-poster-overlay" style="background-image: url(${base_url + 'images/newsletter/view-on-plex.png' if base_url else 'https://i.imgur.com/NSV7q16.png'})"></div> </tr>
</div> </tbody>
</a> </table>
</div> </td>
<div class="card-info-container"> <td class="card-info-container">
<div class="card-info-title nowrap"> <table border="0" cellpadding="0" cellspacing="0">
<a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank">${album['title']}</a> <tbody>
</div> <tr>
<div class="card-info-body"> <td class="card-info-title nowrap">
<div class="nowrap mb5"> <a href="${parameters['pms_web_url']}#!/server/${parameters['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${album['rating_key']}" title="${album['title']}" target="_blank">${album['title']}</a>
<em>${artist['title']} &middot; ${album['track_count']} track${'s' if album['track_count'] > 1 else ''}</em> </td>
</div> </tr>
% if artist['title'].lower() != 'various artists': <tr>
<div> <td class="card-info-body">
${album['summary'][:200] + (album['summary'][200:] and '...')} <p class="nowrap mb5">
</div> <em>${album['parent_title']} &middot; ${album['track_count']} track${'s' if album['track_count'] > 1 else ''}</em>
% endif </p>
</div> % if artist['title'].lower() != 'various artists':
<div class="card-info-footer nowrap"> <p>
% if album['year']: ${album['summary'][:200] + (album['summary'][200:] and '...')}
<span class="badge">${album['year']}</span> </p>
% endif % endif
% if album['genres']: </td>
% for genre in album['genres'][:2]: </tr>
<span class="badge">${genre}</span> <tr>
% endfor <td class="card-info-footer nowrap">
% endif <table border="0" cellpadding="0" cellspacing="0">
% if album['rating']: <tbody>
<span class="star-rating" title="${int(float(album['rating'])/0.1)}%"> <tr>
<div class="star-rating-full nowrap" style="width: ${float(album['rating'])/0.1}%"> <td>
<span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span><span>&#9733;</span> % if album['year']:
</div> <span class="badge">${album['year']}</span>
<div class="star-rating-empty" style="width: ${100-float(album['rating'])/0.1}%"> % endif
<span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span><span>&#9734;</span> % if album['genres']:
</div> % for genre in album['genres'][:2]:
</span> <span class="badge">${genre}</span>
% endif % endfor
</div> % endif
</div> </td>
</div> % if album['rating']:
</div> <% rating = int(round(float(album['rating']) / 2)) %>
% endfor <td class="star-rating-container" title="${int(float(album['rating'])/0.1)}%" align="right">
% endfor % for _ in range(rating):
</div> <span class="star-rating full">&#9733;</span>
% endif % endfor
% for _ in range(5-rating):
<span class="star-rating empty">&#9734;</span>
% endfor
</td>
% endif
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
% else:
<td align="center" valign="top" class="card-instance"></td>
% endif
% endfor
</tr>
% endfor
</tbody>
</table>
</td>
</tr>
% endif
<tr>
<td>
<!-- START FOOTER --> <!-- START FOOTER -->
<div class="footer"> <div class="footer">
<div class="footer-bar"></div> <div class="footer-bar"></div>
@ -857,7 +934,6 @@
</div> </div>
</div> </div>
<!-- END FOOTER --> <!-- END FOOTER -->
</td> </td>
</tr> </tr>

View file

@ -20,6 +20,7 @@ import geoip2.database, geoip2.errors
import gzip import gzip
import hashlib import hashlib
import imghdr import imghdr
from itertools import izip_longest
import ipwhois, ipwhois.exceptions, ipwhois.utils import ipwhois, ipwhois.exceptions, ipwhois.utils
from IPy import IP from IPy import IP
import json import json
@ -974,3 +975,10 @@ def momentjs_to_arrow(format, duration=False):
for f in invalid_formats: for f in invalid_formats:
format = format.replace(f, '') format = format.replace(f, '')
return format return format
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)

View file

@ -413,7 +413,7 @@ class Newsletter(object):
os.makedirs(newsletter_folder) os.makedirs(newsletter_folder)
try: try:
with open(newsletter_file_fp, 'w') as n_file: with open(newsletter_file_fp, 'wb') as n_file:
n_file.write(self.newsletter.encode('utf-8')) n_file.write(self.newsletter.encode('utf-8'))
logger.info(u"Tautulli Newsletters :: %s newsletter saved to %s" % (self.NAME, newsletter_file)) logger.info(u"Tautulli Newsletters :: %s newsletter saved to %s" % (self.NAME, newsletter_file))
@ -661,8 +661,8 @@ class RecentlyAdded(Newsletter):
if self.is_preview or plexpy.CONFIG.NEWSLETTER_SELF_HOSTED: if self.is_preview or plexpy.CONFIG.NEWSLETTER_SELF_HOSTED:
for item in movies + shows + albums: for item in movies + shows + albums:
item['thumb_hash'] = set_hash_image_info(img=item['thumb'], item['thumb_hash'] = set_hash_image_info(img=item['thumb'],
width=300, width=150,
height=450, height=225,
fallback='poster') fallback='poster')
item['art_hash'] = set_hash_image_info(img=item['art'], item['art_hash'] = set_hash_image_info(img=item['art'],
width=500, width=500,