|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
var vent = require('vent');
|
|
|
|
|
var vent = require('vent');
|
|
|
|
|
var Marionette = require('marionette');
|
|
|
|
|
var Backgrid = require('backgrid');
|
|
|
|
|
var ToggleCell = require('../../Cells/EpisodeMonitoredCell');
|
|
|
|
@ -14,68 +14,86 @@ var _ = require('underscore');
|
|
|
|
|
var Messenger = require('../../Shared/Messenger');
|
|
|
|
|
|
|
|
|
|
module.exports = Marionette.Layout.extend({
|
|
|
|
|
template : 'Series/Details/SeasonLayoutTemplate',
|
|
|
|
|
ui : {
|
|
|
|
|
template : 'Series/Details/SeasonLayoutTemplate',
|
|
|
|
|
|
|
|
|
|
ui : {
|
|
|
|
|
seasonSearch : '.x-season-search',
|
|
|
|
|
seasonMonitored : '.x-season-monitored',
|
|
|
|
|
seasonRename : '.x-season-rename'
|
|
|
|
|
},
|
|
|
|
|
events : {
|
|
|
|
|
"click .x-season-monitored" : '_seasonMonitored',
|
|
|
|
|
"click .x-season-search" : '_seasonSearch',
|
|
|
|
|
"click .x-season-rename" : '_seasonRename',
|
|
|
|
|
"click .x-show-hide-episodes" : '_showHideEpisodes',
|
|
|
|
|
"dblclick .series-season h2" : '_showHideEpisodes'
|
|
|
|
|
},
|
|
|
|
|
regions : {episodeGrid : '.x-episode-grid'},
|
|
|
|
|
columns : [{
|
|
|
|
|
name : 'monitored',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : ToggleCell,
|
|
|
|
|
trueClass : 'icon-bookmark',
|
|
|
|
|
falseClass : 'icon-bookmark-empty',
|
|
|
|
|
tooltip : 'Toggle monitored status',
|
|
|
|
|
sortable : false
|
|
|
|
|
}, {
|
|
|
|
|
name : 'episodeNumber',
|
|
|
|
|
label : '#',
|
|
|
|
|
cell : EpisodeNumberCell
|
|
|
|
|
}, {
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : EpisodeWarningCell,
|
|
|
|
|
sortable : false,
|
|
|
|
|
className : 'episode-warning-cell'
|
|
|
|
|
}, {
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : 'Title',
|
|
|
|
|
hideSeriesLink : true,
|
|
|
|
|
cell : EpisodeTitleCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
}, {
|
|
|
|
|
name : 'airDateUtc',
|
|
|
|
|
label : 'Air Date',
|
|
|
|
|
cell : RelativeDateCell
|
|
|
|
|
}, {
|
|
|
|
|
name : 'status',
|
|
|
|
|
label : 'Status',
|
|
|
|
|
cell : EpisodeStatusCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
}, {
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : EpisodeActionsCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
}],
|
|
|
|
|
templateHelpers : function(){
|
|
|
|
|
var episodeCount = this.episodeCollection.filter(function(episode){
|
|
|
|
|
|
|
|
|
|
events : {
|
|
|
|
|
'click .x-season-monitored' : '_seasonMonitored',
|
|
|
|
|
'click .x-season-search' : '_seasonSearch',
|
|
|
|
|
'click .x-season-rename' : '_seasonRename',
|
|
|
|
|
'click .x-show-hide-episodes' : '_showHideEpisodes',
|
|
|
|
|
'dblclick .series-season h2' : '_showHideEpisodes'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
regions : {
|
|
|
|
|
episodeGrid : '.x-episode-grid'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
columns : [
|
|
|
|
|
{
|
|
|
|
|
name : 'monitored',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : ToggleCell,
|
|
|
|
|
trueClass : 'icon-bookmark',
|
|
|
|
|
falseClass : 'icon-bookmark-empty',
|
|
|
|
|
tooltip : 'Toggle monitored status',
|
|
|
|
|
sortable : false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'episodeNumber',
|
|
|
|
|
label : '#',
|
|
|
|
|
cell : EpisodeNumberCell
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : EpisodeWarningCell,
|
|
|
|
|
sortable : false,
|
|
|
|
|
className : 'episode-warning-cell'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : 'Title',
|
|
|
|
|
hideSeriesLink : true,
|
|
|
|
|
cell : EpisodeTitleCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'airDateUtc',
|
|
|
|
|
label : 'Air Date',
|
|
|
|
|
cell : RelativeDateCell
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'status',
|
|
|
|
|
label : 'Status',
|
|
|
|
|
cell : EpisodeStatusCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name : 'this',
|
|
|
|
|
label : '',
|
|
|
|
|
cell : EpisodeActionsCell,
|
|
|
|
|
sortable : false
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
templateHelpers : function() {
|
|
|
|
|
var episodeCount = this.episodeCollection.filter(function(episode) {
|
|
|
|
|
return episode.get('hasFile') || episode.get('monitored') && moment(episode.get('airDateUtc')).isBefore(moment());
|
|
|
|
|
}).length;
|
|
|
|
|
var episodeFileCount = this.episodeCollection.where({hasFile : true}).length;
|
|
|
|
|
|
|
|
|
|
var episodeFileCount = this.episodeCollection.where({ hasFile : true }).length;
|
|
|
|
|
var percentOfEpisodes = 100;
|
|
|
|
|
if(episodeCount > 0) {
|
|
|
|
|
|
|
|
|
|
if (episodeCount > 0) {
|
|
|
|
|
percentOfEpisodes = episodeFileCount / episodeCount * 100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
showingEpisodes : this.showingEpisodes,
|
|
|
|
|
episodeCount : episodeCount,
|
|
|
|
@ -83,24 +101,32 @@ module.exports = Marionette.Layout.extend({
|
|
|
|
|
percentOfEpisodes : percentOfEpisodes
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
initialize : function(options){
|
|
|
|
|
if(!options.episodeCollection) {
|
|
|
|
|
|
|
|
|
|
initialize : function(options) {
|
|
|
|
|
if (!options.episodeCollection) {
|
|
|
|
|
throw 'episodeCollection is needed';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.series = options.series;
|
|
|
|
|
this.fullEpisodeCollection = options.episodeCollection;
|
|
|
|
|
this.episodeCollection = this.fullEpisodeCollection.bySeason(this.model.get('seasonNumber'));
|
|
|
|
|
this._updateEpisodeCollection();
|
|
|
|
|
|
|
|
|
|
this.showingEpisodes = this._shouldShowEpisodes();
|
|
|
|
|
|
|
|
|
|
this.listenTo(this.model, 'sync', this._afterSeasonMonitored);
|
|
|
|
|
this.listenTo(this.episodeCollection, 'sync', this.render);
|
|
|
|
|
|
|
|
|
|
this.listenTo(this.fullEpisodeCollection, 'sync', this._refreshEpsiodes);
|
|
|
|
|
},
|
|
|
|
|
onRender : function(){
|
|
|
|
|
if(this.showingEpisodes) {
|
|
|
|
|
|
|
|
|
|
onRender : function() {
|
|
|
|
|
if (this.showingEpisodes) {
|
|
|
|
|
this._showEpisodes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._setSeasonMonitoredState();
|
|
|
|
|
|
|
|
|
|
CommandController.bindToCommand({
|
|
|
|
|
element : this.ui.seasonSearch,
|
|
|
|
|
command : {
|
|
|
|
@ -109,6 +135,7 @@ module.exports = Marionette.Layout.extend({
|
|
|
|
|
seasonNumber : this.model.get('seasonNumber')
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
CommandController.bindToCommand({
|
|
|
|
|
element : this.ui.seasonRename,
|
|
|
|
|
command : {
|
|
|
|
@ -118,112 +145,143 @@ module.exports = Marionette.Layout.extend({
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
_seasonSearch : function(){
|
|
|
|
|
|
|
|
|
|
_seasonSearch : function() {
|
|
|
|
|
CommandController.Execute('seasonSearch', {
|
|
|
|
|
name : 'seasonSearch',
|
|
|
|
|
seriesId : this.series.id,
|
|
|
|
|
seasonNumber : this.model.get('seasonNumber')
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
_seasonRename : function(){
|
|
|
|
|
|
|
|
|
|
_seasonRename : function() {
|
|
|
|
|
vent.trigger(vent.Commands.ShowRenamePreview, {
|
|
|
|
|
series : this.series,
|
|
|
|
|
seasonNumber : this.model.get('seasonNumber')
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
_seasonMonitored : function(){
|
|
|
|
|
if(!this.series.get('monitored')) {
|
|
|
|
|
|
|
|
|
|
_seasonMonitored : function() {
|
|
|
|
|
if (!this.series.get('monitored')) {
|
|
|
|
|
|
|
|
|
|
Messenger.show({
|
|
|
|
|
message : 'Unable to change monitored state when series is not monitored',
|
|
|
|
|
type : 'error'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var name = 'monitored';
|
|
|
|
|
this.model.set(name, !this.model.get(name));
|
|
|
|
|
this.series.setSeasonMonitored(this.model.get('seasonNumber'));
|
|
|
|
|
|
|
|
|
|
var savePromise = this.series.save().always(this._afterSeasonMonitored.bind(this));
|
|
|
|
|
|
|
|
|
|
this.ui.seasonMonitored.spinForPromise(savePromise);
|
|
|
|
|
},
|
|
|
|
|
_afterSeasonMonitored : function(){
|
|
|
|
|
|
|
|
|
|
_afterSeasonMonitored : function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
_.each(this.episodeCollection.models, function(episode){
|
|
|
|
|
episode.set({monitored : self.model.get('monitored')});
|
|
|
|
|
|
|
|
|
|
_.each(this.episodeCollection.models, function(episode) {
|
|
|
|
|
episode.set({ monitored : self.model.get('monitored') });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.render();
|
|
|
|
|
},
|
|
|
|
|
_setSeasonMonitoredState : function(){
|
|
|
|
|
|
|
|
|
|
_setSeasonMonitoredState : function() {
|
|
|
|
|
this.ui.seasonMonitored.removeClass('icon-spinner icon-spin');
|
|
|
|
|
if(this.model.get('monitored')) {
|
|
|
|
|
|
|
|
|
|
if (this.model.get('monitored')) {
|
|
|
|
|
this.ui.seasonMonitored.addClass('icon-bookmark');
|
|
|
|
|
this.ui.seasonMonitored.removeClass('icon-bookmark-empty');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
this.ui.seasonMonitored.addClass('icon-bookmark-empty');
|
|
|
|
|
this.ui.seasonMonitored.removeClass('icon-bookmark');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_showEpisodes : function(){
|
|
|
|
|
|
|
|
|
|
_showEpisodes : function() {
|
|
|
|
|
this.episodeGrid.show(new Backgrid.Grid({
|
|
|
|
|
columns : this.columns,
|
|
|
|
|
collection : this.episodeCollection,
|
|
|
|
|
className : 'table table-hover season-grid'
|
|
|
|
|
}));
|
|
|
|
|
},
|
|
|
|
|
_shouldShowEpisodes : function(){
|
|
|
|
|
|
|
|
|
|
_shouldShowEpisodes : function() {
|
|
|
|
|
var startDate = moment().add('month', -1);
|
|
|
|
|
var endDate = moment().add('year', 1);
|
|
|
|
|
return this.episodeCollection.some(function(episode){
|
|
|
|
|
|
|
|
|
|
return this.episodeCollection.some(function(episode) {
|
|
|
|
|
var airDate = episode.get('airDateUtc');
|
|
|
|
|
if(airDate) {
|
|
|
|
|
|
|
|
|
|
if (airDate) {
|
|
|
|
|
var airDateMoment = moment(airDate);
|
|
|
|
|
if(airDateMoment.isAfter(startDate) && airDateMoment.isBefore(endDate)) {
|
|
|
|
|
|
|
|
|
|
if (airDateMoment.isAfter(startDate) && airDateMoment.isBefore(endDate)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
_showHideEpisodes : function(){
|
|
|
|
|
if(this.showingEpisodes) {
|
|
|
|
|
|
|
|
|
|
_showHideEpisodes : function() {
|
|
|
|
|
if (this.showingEpisodes) {
|
|
|
|
|
this.showingEpisodes = false;
|
|
|
|
|
this.episodeGrid.close();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
} else {
|
|
|
|
|
this.showingEpisodes = true;
|
|
|
|
|
this._showEpisodes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.templateHelpers.showingEpisodes = this.showingEpisodes;
|
|
|
|
|
this.render();
|
|
|
|
|
},
|
|
|
|
|
_episodeMonitoredToggled : function(options){
|
|
|
|
|
|
|
|
|
|
_episodeMonitoredToggled : function(options) {
|
|
|
|
|
var model = options.model;
|
|
|
|
|
var shiftKey = options.shiftKey;
|
|
|
|
|
if(!this.episodeCollection.get(model.get('id'))) {
|
|
|
|
|
|
|
|
|
|
if (!this.episodeCollection.get(model.get('id'))) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(!shiftKey) {
|
|
|
|
|
|
|
|
|
|
if (!shiftKey) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lastToggled = this.episodeCollection.lastToggled;
|
|
|
|
|
if(!lastToggled) {
|
|
|
|
|
|
|
|
|
|
if (!lastToggled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var currentIndex = this.episodeCollection.indexOf(model);
|
|
|
|
|
var lastIndex = this.episodeCollection.indexOf(lastToggled);
|
|
|
|
|
|
|
|
|
|
var low = Math.min(currentIndex, lastIndex);
|
|
|
|
|
var high = Math.max(currentIndex, lastIndex);
|
|
|
|
|
var range = _.range(low + 1, high);
|
|
|
|
|
|
|
|
|
|
this.episodeCollection.lastToggled = model;
|
|
|
|
|
},
|
|
|
|
|
_updateEpisodeCollection : function(){
|
|
|
|
|
|
|
|
|
|
_updateEpisodeCollection : function() {
|
|
|
|
|
var self = this;
|
|
|
|
|
this.episodeCollection.add(this.fullEpisodeCollection.bySeason(this.model.get('seasonNumber')).models, {merge : true});
|
|
|
|
|
this.episodeCollection.each(function(model){
|
|
|
|
|
|
|
|
|
|
this.episodeCollection.add(this.fullEpisodeCollection.bySeason(this.model.get('seasonNumber')).models, { merge : true });
|
|
|
|
|
|
|
|
|
|
this.episodeCollection.each(function(model) {
|
|
|
|
|
model.episodeCollection = self.episodeCollection;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
_refreshEpsiodes : function(){
|
|
|
|
|
|
|
|
|
|
_refreshEpsiodes : function() {
|
|
|
|
|
this._updateEpisodeCollection();
|
|
|
|
|
this.render();
|
|
|
|
|
}
|
|
|
|
|