mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +00:00
Merge pull request #291 from JackDandy/feature/ChangeEpisodeOverview
Add indication of shows with never aired episodes and other changes to...
This commit is contained in:
commit
f82af467d4
7 changed files with 161 additions and 101 deletions
|
@ -58,6 +58,13 @@
|
|||
* Change the episodes downloaded stat to display e.g. 2843 / 2844 as 99.9% instead of rounding to 100%
|
||||
* Change 'never' episode row color away from blue on Display Show page when indexer airdate is not defined
|
||||
* Add tint to archived episode row colour to differentiate it from downloaded episodes on the Display Show page
|
||||
* Add indication of shows with never aired episodes on Episode Overview page
|
||||
* Add "Collapse" button and visuals for Expanding... and Collapsing... states
|
||||
* Add the number of episodes marked with the status being queried to Episode Overview page
|
||||
* Add indication of shows with never aired episodes on Episode Overview page
|
||||
* Change to separate "Set as wanted" to prevent disaster selection on Episode Overview page
|
||||
* Remove restriction to not display snatched eps link in footer on Episode Overview page
|
||||
* Change the shows episodes count text colour to visually separete from year numbers at the end of show names
|
||||
* Fix release group not recognised from manually downloaded filename
|
||||
|
||||
[develop changelog]
|
||||
|
|
|
@ -382,11 +382,13 @@ ul.tags li a{
|
|||
border:1px solid #111
|
||||
}
|
||||
|
||||
.sickbeardTable tr.header td,
|
||||
.sickbeardTable th{
|
||||
color:#fff;
|
||||
background-color:#15528F
|
||||
}
|
||||
|
||||
.sickbeardTable tr.header td,
|
||||
.sickbeardTable th,
|
||||
.sickbeardTable td{
|
||||
border-top:1px solid #222;
|
||||
|
|
|
@ -1324,6 +1324,7 @@ span.snatched b{
|
|||
clear:both
|
||||
}
|
||||
|
||||
.sickbeardTable tr.header td,
|
||||
.sickbeardTable th{
|
||||
color:#fff;
|
||||
text-align:center;
|
||||
|
@ -1331,13 +1332,18 @@ span.snatched b{
|
|||
white-space:nowrap
|
||||
}
|
||||
|
||||
.sickbeardTable th,
|
||||
.sickbeardTable tr.header td,
|
||||
.sickbeardTable th,
|
||||
.sickbeardTable td{
|
||||
border-top:1px solid #fff;
|
||||
border-left:1px solid #fff;
|
||||
padding:4px
|
||||
}
|
||||
|
||||
.sickbeardTable tr.header td{
|
||||
padding:4px 8px
|
||||
}
|
||||
|
||||
th.row-seasonheader{
|
||||
border:none;
|
||||
background-color:#fff;
|
||||
|
@ -2247,6 +2253,7 @@ div.metadataDiv .disabled{
|
|||
manage*.tmpl
|
||||
========================================================================== */
|
||||
|
||||
.sickbeardTable tr.header td,
|
||||
.manageTable th{
|
||||
white-space:normal;
|
||||
line-height:24px
|
||||
|
@ -2300,6 +2307,11 @@ a.whitelink{
|
|||
color:#fff
|
||||
}
|
||||
|
||||
input.get_more_eps,
|
||||
input.get_less_eps{
|
||||
display:none
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
404.tmpl
|
||||
========================================================================== */
|
||||
|
|
|
@ -56,11 +56,8 @@
|
|||
(
|
||||
'',
|
||||
' (<span class="footerhighlight">+%s</span> snatched)'\
|
||||
% (
|
||||
str(ep_snatched),
|
||||
'<a href="%s/manage/episodeStatuses?whichStatus=2" title="View overview of snatched episodes">%s</a>'\
|
||||
% (localRoot, str(ep_snatched))
|
||||
)['Episode Overview' != localheader]
|
||||
% '<a href="%s/manage/episodeStatuses?whichStatus=2" title="View overview of snatched episodes">%s</a>'
|
||||
% (localRoot, str(ep_snatched))
|
||||
)[0 < ep_snatched]
|
||||
%> / <span class="footerhighlight">$ep_total</span> episodes downloaded $ep_percentage
|
||||
| recent search: <span class="footerhighlight"><%= str(sickbeard.recentSearchScheduler.timeLeft()).split('.')[0] %></span>
|
||||
|
|
|
@ -16,70 +16,96 @@
|
|||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
#if not $whichStatus or ($whichStatus and not $ep_counts):
|
||||
#if not $whichStatus or ($whichStatus and not $ep_counts)
|
||||
|
||||
#if $whichStatus:
|
||||
<h3>None of your episodes have status <span class="grey-text">$common.statusStrings[$int($whichStatus)]</span></h3>
|
||||
#end if
|
||||
#if $whichStatus:
|
||||
<h3>no episodes have status <span class="grey-text">$common.statusStrings[$int($whichStatus)].lower()</span></h3>
|
||||
#end if
|
||||
|
||||
<form action="$sbRoot/manage/episodeStatuses" method="get">
|
||||
Manage episodes with status <select name="whichStatus" class="form-control form-control-inline input-sm">
|
||||
#for $curStatus in [$common.SKIPPED, $common.UNKNOWN, $common.SNATCHED, $common.WANTED, $common.ARCHIVED, $common.IGNORED]:
|
||||
<option value="$curStatus">$common.statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
<input class="btn btn-inline" type="submit" value="Manage" />
|
||||
</form>
|
||||
<form action="$sbRoot/manage/episodeStatuses" method="get">
|
||||
|
||||
Manage episodes with status
|
||||
<select name="whichStatus" class="form-control form-control-inline input-sm" style="margin:0 10px">
|
||||
|
||||
#for $curStatus in [$common.SKIPPED, $common.UNKNOWN, $common.SNATCHED, $common.WANTED, $common.ARCHIVED, $common.IGNORED]:
|
||||
<option value="$curStatus">$common.statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
|
||||
</select>
|
||||
<input class="btn btn-inline" type="submit" value="Manage">
|
||||
</form>
|
||||
|
||||
#else
|
||||
|
||||
#if $whichStatus in ($common.ARCHIVED, $common.IGNORED, $common.SNATCHED):
|
||||
#set $row_class = 'good'
|
||||
#else
|
||||
#set $row_class = $common.Overview.overviewStrings[$whichStatus]
|
||||
#end if
|
||||
|
||||
#set $statusList = [$common.SKIPPED, $common.ARCHIVED, $common.IGNORED]
|
||||
#if $int($whichStatus) in $statusList
|
||||
$statusList.remove($int($whichStatus))
|
||||
#end if
|
||||
|
||||
#if $int($whichStatus) in [$common.SNATCHED, $common.SNATCHED_PROPER]
|
||||
$statusList.append($common.FAILED)
|
||||
#end if
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/manageEpisodeStatuses.js?$sbPID"></script>
|
||||
|
||||
<form action="$sbRoot/manage/changeEpisodeStatuses" method="post">
|
||||
<input type="hidden" id="oldStatus" name="oldStatus" value="$whichStatus" />
|
||||
<form action="$sbRoot/manage/changeEpisodeStatuses" method="post">
|
||||
<input type="hidden" id="oldStatus" name="oldStatus" value="$whichStatus">
|
||||
|
||||
<h3>${len($sorted_show_ids)} Shows containing <span class="grey-text">$common.statusStrings[$int($whichStatus)]</span> episodes</h3>
|
||||
<h3><span class="grey-text">$ep_count</span> episode#echo ('s', '')[1 == $ep_count]# marked <span class="grey-text">$common.statusStrings[$int($whichStatus)].lower()</span> in <span class="grey-text">${len($sorted_show_ids)}</span> show#echo ('s', '')[1 == len($sorted_show_ids)]#</h3>
|
||||
|
||||
#if $whichStatus in ($common.ARCHIVED, $common.IGNORED, $common.SNATCHED):
|
||||
#set $row_class = 'good'
|
||||
#else
|
||||
#set $row_class = $common.Overview.overviewStrings[$whichStatus]
|
||||
#end if
|
||||
<input type="hidden" id="row_class" value="$row_class" />
|
||||
<input type="hidden" id="row_class" value="$row_class">
|
||||
|
||||
<div class="form-group">
|
||||
Set checked shows/episodes to <select name="newStatus" class="form-control form-control-inline input-sm">
|
||||
#set $statusList = [$common.SKIPPED, $common.WANTED, $common.ARCHIVED, $common.IGNORED]
|
||||
#if $int($whichStatus) in $statusList
|
||||
$statusList.remove($int($whichStatus))
|
||||
#end if
|
||||
<div class="form-group">
|
||||
<span>Set checked shows/episodes to</span>
|
||||
<select name="newStatus" class="form-control form-control-inline input-sm" style="margin:0 10px 0 5px">
|
||||
#for $curStatus in $statusList:
|
||||
<option value="$curStatus">$common.statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
<input class="btn btn-inline go" type="submit" value="Go">
|
||||
|
||||
#if $int($whichStatus) in [$common.SNATCHED, $common.SNATCHED_PROPER]
|
||||
$statusList.append($common.FAILED)
|
||||
#end if
|
||||
<span class="red-text" style="margin:0 0 0 30px">Override checked status to</span>
|
||||
<select name="wantedStatus" class="form-control form-control-inline input-sm" style="margin:0 10px 0 5px">
|
||||
<option value="$common.UNKNOWN">nothing</option>
|
||||
<option value="$common.WANTED">$common.statusStrings[$common.WANTED]</option>
|
||||
</select>
|
||||
<input class="btn btn-inline go" type="submit" value="Go">
|
||||
</div>
|
||||
|
||||
#for $curStatus in $statusList:
|
||||
<option value="$curStatus">$common.statusStrings[$curStatus]</option>
|
||||
#end for
|
||||
</select>
|
||||
<input class="btn btn-inline go" type="submit" value="Go" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="button" class="btn btn-xs selectAllShows" value="Select all">
|
||||
<input type="button" class="btn btn-xs unselectAllShows" value="Clear all">
|
||||
<input type="button" class="btn btn-xs expandAll" value="Expand All Shows">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="button" class="btn btn-xs selectAllShows" value="Select all">
|
||||
<input type="button" class="btn btn-xs unselectAllShows" value="Clear all">
|
||||
<input type="button" class="btn btn-xs expandAll" value="Expand All Shows">
|
||||
</div>
|
||||
|
||||
<table class="sickbeardTable manageTable" cellspacing="1" border="0" cellpadding="0">
|
||||
#for $cur_indexer_id in $sorted_show_ids:
|
||||
<tr id="$cur_indexer_id">
|
||||
<th><input type="checkbox" class="allCheck" id="allCheck-$cur_indexer_id" name="$cur_indexer_id-all" /></th>
|
||||
<th colspan="2" style="width: 100%; text-align: left;"><a class="whitelink" href="$sbRoot/home/displayShow?show=$cur_indexer_id">$show_names[$cur_indexer_id]</a> ($ep_counts[$cur_indexer_id]) <input type="button" class="pull-right get_more_eps btn" id="$cur_indexer_id" value="Expand" /></th>
|
||||
</tr>
|
||||
#end for
|
||||
</table>
|
||||
</form>
|
||||
<table class="sickbeardTable manageTable" cellspacing="1" border="0" cellpadding="0">
|
||||
<thead></thead>
|
||||
<tbody>
|
||||
#for $cur_indexer_id in $sorted_show_ids:
|
||||
#if 0 == int($never_counts[$cur_indexer_id])
|
||||
#set $output = '%d' % $ep_counts[$cur_indexer_id]
|
||||
#elif $ep_counts[$cur_indexer_id] != $never_counts[$cur_indexer_id]
|
||||
#set $diff = $ep_counts[$cur_indexer_id] - $never_counts[$cur_indexer_id]
|
||||
#set $output = '%d' % $diff + ('', (' episode%s plus %s never with an airdate' % (('s', '')[1 == $ep_counts[$cur_indexer_id]], $never_counts[$cur_indexer_id])))[0 < $never_counts[$cur_indexer_id]]
|
||||
#else
|
||||
#set $output = '%s never with an airdate' % (('all %s %ss', '%s %s')[1 == $ep_counts[$cur_indexer_id]] % ($ep_counts[$cur_indexer_id], 'episode'))
|
||||
#end if
|
||||
<tr id="$cur_indexer_id" class="header">
|
||||
<td><input type="checkbox" class="allCheck" id="allCheck-$cur_indexer_id" name="$cur_indexer_id-all"></td>
|
||||
<td colspan="2" style="width:100%;text-align:left">
|
||||
<a class="whitelink" href="$sbRoot/home/displayShow?show=$cur_indexer_id">$show_names[$cur_indexer_id]</a> <span style="color:#999">($output)</span><input type="button" class="pull-right get_more_eps btn" id="$cur_indexer_id-more" value="Expand"><input type="button" class="pull-right get_less_eps btn" id="$cur_indexer_id-less" value="Collapse">
|
||||
</td>
|
||||
</tr>
|
||||
#end for
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
#end if
|
||||
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
function make_row(indexer_id, season, episode, name, checked) {
|
||||
function make_row(indexer_id, season, episode, name, checked, airdate_never) {
|
||||
var checkedbox = (checked ? ' checked' : ''),
|
||||
row_class = $('#row_class').val();
|
||||
row_class = $('#row_class').val(),
|
||||
ep_id = season + 'x' + episode;
|
||||
|
||||
return ' <tr class="' + row_class + '">'
|
||||
return ' <tr id="ep-' + indexer_id + '-' + ep_id + '" class="' + (airdate_never ? 'airdate-never' : row_class) + '">'
|
||||
+ ' <td class="tableleft" align="center">'
|
||||
+ '<input type="checkbox"'
|
||||
+ ' class="' + indexer_id + '-epcheck"'
|
||||
+ ' name="' + indexer_id + '-' + season + 'x' + episode + '"'
|
||||
+ ' name="' + indexer_id + '-' + ep_id + '"'
|
||||
+ checkedbox+'></td>'
|
||||
+ ' <td>' + season + 'x' + episode + '</td>'
|
||||
+ ' <td class="tableright" style="width: 100%">' + name + '</td>'
|
||||
+ ' <td>' + ep_id + '</td>'
|
||||
+ ' <td class="tableright" style="width: 100%">' + name + (airdate_never ? ' (<strong><em>airdate is never, this should change in time</em></strong>)' : '') + '</td>'
|
||||
+ ' </tr>';
|
||||
}
|
||||
|
||||
|
@ -27,48 +28,52 @@ $(document).ready(function() {
|
|||
$('.' + indexer_id + '-epcheck').prop('checked', $(this).prop('checked'));
|
||||
});
|
||||
|
||||
$('.get_more_eps').click(function(){
|
||||
var cur_indexer_id = $(this).attr('id');
|
||||
var checked = $('#allCheck-' + cur_indexer_id).prop('checked');
|
||||
var last_row = $('tr#' + cur_indexer_id);
|
||||
|
||||
$.getJSON(sbRoot + '/manage/showEpisodeStatuses',
|
||||
{
|
||||
indexer_id: cur_indexer_id,
|
||||
whichStatus: $('#oldStatus').val()
|
||||
},
|
||||
function (data) {
|
||||
$.each(data, function(season,eps){
|
||||
$.each(eps, function(episode, name) {
|
||||
last_row.after(make_row(cur_indexer_id, season, episode, name, checked));
|
||||
});
|
||||
});
|
||||
});
|
||||
$(this).hide();
|
||||
($('.get_more_eps:visible').length == 0 ? $('.expandAll').hide() : '');
|
||||
});
|
||||
$('.get_more_eps').show();
|
||||
function show_episodes(btn_element) {
|
||||
var match = btn_element.attr('id').match(/(.*)[-](.*)/);
|
||||
if (null == match)
|
||||
return false;
|
||||
|
||||
$('.expandAll').click(function() {
|
||||
$('.get_more_eps').each(function() {
|
||||
var cur_indexer_id = $(this).attr('id');
|
||||
var checked = $('#allCheck-' + cur_indexer_id).prop('checked');
|
||||
var last_row = $('tr#' + cur_indexer_id);
|
||||
var cur_indexer_id = match[1], action = match[2], checked = $('#allCheck-' + cur_indexer_id).prop('checked'),
|
||||
show_header = $('tr#' + cur_indexer_id), episode_rows = $('tr[id*="ep-' + cur_indexer_id + '"]'),
|
||||
void_var = 'more' == action && episode_rows.show() || episode_rows.hide();
|
||||
|
||||
$('input#' + match[0]).val('more' == action ? 'Expanding...' : 'Collapsing...');
|
||||
|
||||
if (0 == episode_rows.length) {
|
||||
$.getJSON(sbRoot + '/manage/showEpisodeStatuses',
|
||||
{
|
||||
indexer_id: cur_indexer_id,
|
||||
whichStatus: $('#oldStatus').val()
|
||||
},
|
||||
function (data) {
|
||||
$.each(data, function(season, eps) {
|
||||
$.each(eps, function(episode, name) {
|
||||
last_row.after(make_row(cur_indexer_id, season, episode, name, checked));
|
||||
$.each(data, function(season, eps){
|
||||
$.each(eps, function(episode, meta) {
|
||||
show_header.after(make_row(cur_indexer_id, season, episode, meta.name, checked, meta.airdate_never));
|
||||
});
|
||||
});
|
||||
$('input#' + match[0]).val('more' == action ? 'Expand' : 'Collapse');
|
||||
btn_element.hide();
|
||||
$('input[id="' + cur_indexer_id + '-' + ('more' == action ? 'less' : 'more') + '"]').show();
|
||||
});
|
||||
$(this).hide();
|
||||
});
|
||||
} else {
|
||||
$('input#' + match[0]).val('more' == action ? 'Expand' : 'Collapse');
|
||||
btn_element.hide();
|
||||
$('input[id="' + cur_indexer_id + '-' + ('more' == action ? 'less' : 'more') + '"]').show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$('.get_more_eps,.get_less_eps').click(function(){
|
||||
show_episodes($(this));
|
||||
($('.get_more_eps:visible').length == 0 ? $('.expandAll').hide() : '');
|
||||
});
|
||||
|
||||
$('.expandAll').click(function() {
|
||||
$(this).hide();
|
||||
$('.get_more_eps').each(function() {
|
||||
show_episodes($(this));
|
||||
});
|
||||
});
|
||||
|
||||
// selects all visible episode checkboxes.
|
||||
|
|
|
@ -1487,7 +1487,7 @@ class Home(MainHandler):
|
|||
sql_l = []
|
||||
for curEp in eps.split('|'):
|
||||
|
||||
logger.log(u'Attempting to set status on episode ' + curEp + ' to ' + status, logger.DEBUG)
|
||||
logger.log(u'Attempting to set status on episode %s to %s' % (curEp, status), logger.DEBUG)
|
||||
|
||||
epInfo = curEp.split('x')
|
||||
|
||||
|
@ -2481,7 +2481,7 @@ class Manage(MainHandler):
|
|||
|
||||
myDB = db.DBConnection()
|
||||
cur_show_results = myDB.select(
|
||||
'SELECT season, episode, name FROM tv_episodes WHERE showid = ? AND season != 0 AND status IN (' + ','.join(
|
||||
'SELECT season, episode, name, airdate FROM tv_episodes WHERE showid = ? AND season != 0 AND status IN (' + ','.join(
|
||||
['?'] * len(status_list)) + ')', [int(indexer_id)] + status_list)
|
||||
|
||||
result = {}
|
||||
|
@ -2492,7 +2492,7 @@ class Manage(MainHandler):
|
|||
if cur_season not in result:
|
||||
result[cur_season] = {}
|
||||
|
||||
result[cur_season][cur_episode] = cur_result['name']
|
||||
result[cur_season][cur_episode] = {'name': cur_result['name'], 'airdate_never': (True, False)[1000 < int(cur_result['airdate'])]}
|
||||
|
||||
return json.dumps(result)
|
||||
|
||||
|
@ -2516,12 +2516,14 @@ class Manage(MainHandler):
|
|||
|
||||
myDB = db.DBConnection()
|
||||
status_results = myDB.select(
|
||||
'SELECT show_name, tv_shows.indexer_id as indexer_id FROM tv_episodes, tv_shows WHERE tv_episodes.status IN (' + ','.join(
|
||||
'SELECT show_name, tv_shows.indexer_id as indexer_id, airdate FROM tv_episodes, tv_shows WHERE tv_episodes.status IN (' + ','.join(
|
||||
['?'] * len(
|
||||
status_list)) + ') AND season != 0 AND tv_episodes.showid = tv_shows.indexer_id ORDER BY show_name',
|
||||
status_list)
|
||||
|
||||
ep_counts = {}
|
||||
ep_count = 0
|
||||
never_counts = {}
|
||||
show_names = {}
|
||||
sorted_show_ids = []
|
||||
for cur_status_result in status_results:
|
||||
|
@ -2530,6 +2532,11 @@ class Manage(MainHandler):
|
|||
ep_counts[cur_indexer_id] = 1
|
||||
else:
|
||||
ep_counts[cur_indexer_id] += 1
|
||||
ep_count += 1
|
||||
if cur_indexer_id not in never_counts:
|
||||
never_counts[cur_indexer_id] = 0
|
||||
if 1000 > int(cur_status_result['airdate']):
|
||||
never_counts[cur_indexer_id] += 1
|
||||
|
||||
show_names[cur_indexer_id] = cur_status_result['show_name']
|
||||
if cur_indexer_id not in sorted_show_ids:
|
||||
|
@ -2537,11 +2544,12 @@ class Manage(MainHandler):
|
|||
|
||||
t.show_names = show_names
|
||||
t.ep_counts = ep_counts
|
||||
t.ep_count = ep_count
|
||||
t.never_counts = never_counts
|
||||
t.sorted_show_ids = sorted_show_ids
|
||||
return t.respond()
|
||||
|
||||
def changeEpisodeStatuses(self, oldStatus, newStatus, *args, **kwargs):
|
||||
|
||||
def changeEpisodeStatuses(self, oldStatus, newStatus, wantedStatus=sickbeard.common.UNKNOWN, *args, **kwargs):
|
||||
status_list = [int(oldStatus)]
|
||||
if status_list[0] == SNATCHED:
|
||||
status_list = Quality.SNATCHED + Quality.SNATCHED_PROPER
|
||||
|
@ -2550,17 +2558,20 @@ class Manage(MainHandler):
|
|||
|
||||
# make a list of all shows and their associated args
|
||||
for arg in kwargs:
|
||||
indexer_id, what = arg.split('-')
|
||||
|
||||
# we don't care about unchecked checkboxes
|
||||
if kwargs[arg] != 'on':
|
||||
continue
|
||||
|
||||
indexer_id, what = arg.split('-')
|
||||
|
||||
if indexer_id not in to_change:
|
||||
to_change[indexer_id] = []
|
||||
|
||||
to_change[indexer_id].append(what)
|
||||
|
||||
if sickbeard.common.WANTED == int(wantedStatus):
|
||||
newStatus = sickbeard.common.WANTED
|
||||
|
||||
myDB = db.DBConnection()
|
||||
for cur_indexer_id in to_change:
|
||||
|
||||
|
|
Loading…
Reference in a new issue