diff --git a/CHANGES.md b/CHANGES.md
index af856ea6..2260c12b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -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]
diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css
index d421f1d4..71caaf03 100644
--- a/gui/slick/css/dark.css
+++ b/gui/slick/css/dark.css
@@ -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;
diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css
index ae96007e..49dad9e1 100644
--- a/gui/slick/css/style.css
+++ b/gui/slick/css/style.css
@@ -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
========================================================================== */
diff --git a/gui/slick/interfaces/default/inc_bottom.tmpl b/gui/slick/interfaces/default/inc_bottom.tmpl
index b2d0d809..f194a3c9 100644
--- a/gui/slick/interfaces/default/inc_bottom.tmpl
+++ b/gui/slick/interfaces/default/inc_bottom.tmpl
@@ -56,11 +56,8 @@
(
'',
' ( snatched)'\
-% (
- str(ep_snatched),
- '%s'\
- % (localRoot, str(ep_snatched))
- )['Episode Overview' != localheader]
+% '%s'
+ % (localRoot, str(ep_snatched))
)[0 < ep_snatched]
%> / episodes downloaded $ep_percentage
| recent search:
diff --git a/gui/slick/interfaces/default/manage_episodeStatuses.tmpl b/gui/slick/interfaces/default/manage_episodeStatuses.tmpl
index b9587f86..7cabd7cf 100644
--- a/gui/slick/interfaces/default/manage_episodeStatuses.tmpl
+++ b/gui/slick/interfaces/default/manage_episodeStatuses.tmpl
@@ -16,70 +16,96 @@
$title
#end if
-#if not $whichStatus or ($whichStatus and not $ep_counts):
+#if not $whichStatus or ($whichStatus and not $ep_counts)
-#if $whichStatus:
- None of your episodes have status $common.statusStrings[$int($whichStatus)]
-#end if
+ #if $whichStatus:
+ no episodes have status $common.statusStrings[$int($whichStatus)].lower()
+ #end if
-
+
#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
+
-
+
+
+
+ #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
+
+ #end for
+
+
+
#end if
diff --git a/gui/slick/js/manageEpisodeStatuses.js b/gui/slick/js/manageEpisodeStatuses.js
index 8b31e102..d002dc94 100644
--- a/gui/slick/js/manageEpisodeStatuses.js
+++ b/gui/slick/js/manageEpisodeStatuses.js
@@ -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 ' '
+ return '
'
+ ' '
+ ' | '
- + ' ' + season + 'x' + episode + ' | '
- + ' ' + name + ' | '
+ + ' ' + ep_id + ' | '
+ + ' ' + name + (airdate_never ? ' (airdate is never, this should change in time)' : '') + ' | '
+ '
';
}
@@ -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.
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 13f59897..76842872 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -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: