Added season pass for toggling monitored status of seasons
Linked from missing
This commit is contained in:
parent
694714726c
commit
6ca17942f0
|
@ -14,13 +14,20 @@ namespace NzbDrone.Api.Seasons
|
||||||
|
|
||||||
GetResourceAll = GetSeasons;
|
GetResourceAll = GetSeasons;
|
||||||
UpdateResource = SetMonitored;
|
UpdateResource = SetMonitored;
|
||||||
|
|
||||||
|
Post["/pass"] = x => SetSeasonPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SeasonResource> GetSeasons()
|
private List<SeasonResource> GetSeasons()
|
||||||
{
|
{
|
||||||
var seriesId = Request.Query.SeriesId;
|
var seriesId = Request.Query.SeriesId;
|
||||||
|
|
||||||
return ToListResource<Season>(() => _seasonService.GetSeasonsBySeries(seriesId));
|
if (seriesId.HasValue)
|
||||||
|
{
|
||||||
|
return ToListResource<Season>(() => _seasonService.GetSeasonsBySeries(seriesId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ToListResource<Season>(() => _seasonService.GetAllSeasons());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SeasonResource SetMonitored(SeasonResource seasonResource)
|
private SeasonResource SetMonitored(SeasonResource seasonResource)
|
||||||
|
@ -29,5 +36,13 @@ namespace NzbDrone.Api.Seasons
|
||||||
|
|
||||||
return seasonResource;
|
return seasonResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SeasonResource> SetSeasonPass()
|
||||||
|
{
|
||||||
|
var seriesId = Request.Form.SeriesId;
|
||||||
|
var seasonNumber = Request.Form.SeasonNumber;
|
||||||
|
|
||||||
|
return ToListResource<Season>(() => _seasonService.SetSeasonPass(seriesId, seasonNumber));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
|
@ -16,10 +16,11 @@ define(
|
||||||
'Logs/Files/Layout',
|
'Logs/Files/Layout',
|
||||||
'Release/Layout',
|
'Release/Layout',
|
||||||
'System/Layout',
|
'System/Layout',
|
||||||
|
'SeasonPass/Layout',
|
||||||
'Shared/NotFoundView',
|
'Shared/NotFoundView',
|
||||||
'Shared/Modal/Region'
|
'Shared/Modal/Region'
|
||||||
], function (App, Marionette, HistoryLayout, SettingsLayout, AddSeriesLayout, SeriesIndexLayout, SeriesDetailsLayout, SeriesCollection, MissingLayout, SeriesModel, CalendarLayout,
|
], function (App, Marionette, HistoryLayout, SettingsLayout, AddSeriesLayout, SeriesIndexLayout, SeriesDetailsLayout, SeriesCollection, MissingLayout, SeriesModel, CalendarLayout,
|
||||||
LogsLayout, LogFileLayout, ReleaseLayout, SystemLayout, NotFoundView) {
|
LogsLayout, LogFileLayout, ReleaseLayout, SystemLayout, SeasonPassLayout, NotFoundView) {
|
||||||
return Marionette.Controller.extend({
|
return Marionette.Controller.extend({
|
||||||
|
|
||||||
series: function () {
|
series: function () {
|
||||||
|
@ -40,11 +41,6 @@ define(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
_showSeriesDetail: function(seriesModel){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addSeries: function (action) {
|
addSeries: function (action) {
|
||||||
this._setTitle('Add Series');
|
this._setTitle('Add Series');
|
||||||
App.mainRegion.show(new AddSeriesLayout({action: action}));
|
App.mainRegion.show(new AddSeriesLayout({action: action}));
|
||||||
|
@ -55,7 +51,6 @@ define(
|
||||||
App.mainRegion.show(new CalendarLayout());
|
App.mainRegion.show(new CalendarLayout());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
settings: function (action) {
|
settings: function (action) {
|
||||||
this._setTitle('Settings');
|
this._setTitle('Settings');
|
||||||
App.mainRegion.show(new SettingsLayout({action: action}));
|
App.mainRegion.show(new SettingsLayout({action: action}));
|
||||||
|
@ -95,6 +90,11 @@ define(
|
||||||
App.mainRegion.show(new SystemLayout());
|
App.mainRegion.show(new SystemLayout());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
seasonPass: function () {
|
||||||
|
this._setTitle('Season Pass');
|
||||||
|
App.mainRegion.show(new SeasonPassLayout());
|
||||||
|
},
|
||||||
|
|
||||||
notFound: function () {
|
notFound: function () {
|
||||||
this._setTitle('Not Found');
|
this._setTitle('Not Found');
|
||||||
App.mainRegion.show(new NotFoundView(this));
|
App.mainRegion.show(new NotFoundView(this));
|
||||||
|
|
|
@ -9,8 +9,9 @@ define(
|
||||||
'Cells/EpisodeTitleCell',
|
'Cells/EpisodeTitleCell',
|
||||||
'Cells/RelativeDateCell',
|
'Cells/RelativeDateCell',
|
||||||
'Shared/Grid/Pager',
|
'Shared/Grid/Pager',
|
||||||
|
'Shared/Toolbar/ToolbarLayout',
|
||||||
'Shared/LoadingView'
|
'Shared/LoadingView'
|
||||||
], function (Marionette, Backgrid, MissingCollection, SeriesTitleCell, EpisodeNumberCell, EpisodeTitleCell, RelativeDateCell, GridPager, LoadingView) {
|
], function (Marionette, Backgrid, MissingCollection, SeriesTitleCell, EpisodeNumberCell, EpisodeTitleCell, RelativeDateCell, GridPager, ToolbarLayout, LoadingView) {
|
||||||
return Marionette.Layout.extend({
|
return Marionette.Layout.extend({
|
||||||
template: 'Missing/MissingLayoutTemplate',
|
template: 'Missing/MissingLayoutTemplate',
|
||||||
|
|
||||||
|
@ -47,6 +48,19 @@ define(
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
leftSideButtons: {
|
||||||
|
type : 'default',
|
||||||
|
storeState: false,
|
||||||
|
items :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title : 'Season Pass',
|
||||||
|
icon : 'icon-bookmark',
|
||||||
|
route : 'seasonpass'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
_showTable: function () {
|
_showTable: function () {
|
||||||
this.missing.show(new Backgrid.Grid({
|
this.missing.show(new Backgrid.Grid({
|
||||||
columns : this.columns,
|
columns : this.columns,
|
||||||
|
@ -69,6 +83,18 @@ define(
|
||||||
this.missingCollection.fetch().done(function () {
|
this.missingCollection.fetch().done(function () {
|
||||||
self._showTable();
|
self._showTable();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._showToolbar();
|
||||||
|
},
|
||||||
|
|
||||||
|
_showToolbar: function () {
|
||||||
|
this.toolbar.show(new ToolbarLayout({
|
||||||
|
left :
|
||||||
|
[
|
||||||
|
this.leftSideButtons
|
||||||
|
],
|
||||||
|
context: this
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,6 +26,7 @@ require(
|
||||||
'logs/:action' : 'logs',
|
'logs/:action' : 'logs',
|
||||||
'rss' : 'rss',
|
'rss' : 'rss',
|
||||||
'system' : 'system',
|
'system' : 'system',
|
||||||
|
'seasonpass' : 'seasonPass',
|
||||||
':whatever' : 'notFound'
|
':whatever' : 'notFound'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette',
|
||||||
|
'Series/SeriesCollection',
|
||||||
|
'Series/SeasonCollection',
|
||||||
|
'SeasonPass/SeriesCollectionView',
|
||||||
|
'Shared/LoadingView'
|
||||||
|
], function (Marionette,
|
||||||
|
SeriesCollection,
|
||||||
|
SeasonCollection,
|
||||||
|
SeriesCollectionView,
|
||||||
|
LoadingView) {
|
||||||
|
return Marionette.Layout.extend({
|
||||||
|
template: 'SeasonPass/LayoutTemplate',
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
series: '#x-series'
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow: function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.series.show(new LoadingView());
|
||||||
|
|
||||||
|
this.seriesCollection = SeriesCollection;
|
||||||
|
this.seasonCollection = new SeasonCollection();
|
||||||
|
|
||||||
|
var promise = this.seasonCollection.fetch();
|
||||||
|
|
||||||
|
promise.done(function () {
|
||||||
|
self.series.show(new SeriesCollectionView({
|
||||||
|
collection: self.seriesCollection,
|
||||||
|
seasonCollection: self.seasonCollection
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<div class="alert alert-info">Season Pass allows you to quickly change the monitored status of seasons for all your series in one place</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<div id="x-series"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,26 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette',
|
||||||
|
'SeasonPass/SeriesLayout'
|
||||||
|
], function (Marionette, SeriesLayout) {
|
||||||
|
return Marionette.CollectionView.extend({
|
||||||
|
|
||||||
|
itemView: SeriesLayout,
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
|
||||||
|
if (!options.seasonCollection) {
|
||||||
|
throw 'seasonCollection is needed';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.seasonCollection = options.seasonCollection;
|
||||||
|
},
|
||||||
|
|
||||||
|
itemViewOptions: function () {
|
||||||
|
return {
|
||||||
|
seasonCollection: this.seasonCollection
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,117 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette',
|
||||||
|
'backgrid',
|
||||||
|
'Series/SeasonCollection',
|
||||||
|
'Cells/ToggleCell',
|
||||||
|
'Shared/Actioneer'
|
||||||
|
], function (Marionette, Backgrid, SeasonCollection, ToggleCell, Actioneer) {
|
||||||
|
return Marionette.Layout.extend({
|
||||||
|
template: 'SeasonPass/SeriesLayoutTemplate',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
seasonSelect: '.x-season-select',
|
||||||
|
expander : '.x-expander',
|
||||||
|
seasonGrid : '.x-season-grid'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'change .x-season-select': '_seasonSelected',
|
||||||
|
'click .x-expander' : '_expand'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
seasonGrid: '.x-season-grid'
|
||||||
|
},
|
||||||
|
|
||||||
|
columns:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name : 'monitored',
|
||||||
|
label : '',
|
||||||
|
cell : ToggleCell,
|
||||||
|
trueClass : 'icon-bookmark',
|
||||||
|
falseClass: 'icon-bookmark-empty',
|
||||||
|
tooltip : 'Toggle monitored status',
|
||||||
|
sortable : false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'seasonNumber',
|
||||||
|
label: 'Season',
|
||||||
|
cell : Backgrid.IntegerCell.extend({
|
||||||
|
className: 'season-number-cell'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
this.seasonCollection = options.seasonCollection.bySeries(this.model.get('id'));
|
||||||
|
this.model.set('seasons', this.seasonCollection);
|
||||||
|
this.expanded = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.seasonGrid.show(new Backgrid.Grid({
|
||||||
|
columns : this.columns,
|
||||||
|
collection: this.seasonCollection,
|
||||||
|
className : 'table table-condensed season-grid span5'
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!this.expanded) {
|
||||||
|
this.seasonGrid.$el.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setExpanderIcon();
|
||||||
|
},
|
||||||
|
|
||||||
|
_seasonSelected: function () {
|
||||||
|
var self = this;
|
||||||
|
var seasonNumber = parseInt(this.ui.seasonSelect.val());
|
||||||
|
|
||||||
|
if (seasonNumber == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var promise = $.ajax({
|
||||||
|
url: this.seasonCollection.url + '/pass',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
seriesId: this.model.get('id'),
|
||||||
|
seasonNumber: seasonNumber
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done(function (data) {
|
||||||
|
self.seasonCollection = new SeasonCollection(data);
|
||||||
|
self.render();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_expand: function () {
|
||||||
|
if (this.expanded) {
|
||||||
|
this.ui.seasonGrid.slideUp();
|
||||||
|
this.expanded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
this.ui.seasonGrid.slideDown();
|
||||||
|
this.expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setExpanderIcon();
|
||||||
|
},
|
||||||
|
|
||||||
|
_setExpanderIcon: function () {
|
||||||
|
if (this.expanded) {
|
||||||
|
this.ui.expander.removeClass('icon-chevron-right');
|
||||||
|
this.ui.expander.addClass('icon-chevron-down');
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
this.ui.expander.removeClass('icon-chevron-down');
|
||||||
|
this.ui.expander.addClass('icon-chevron-right');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div class="seasonpass-series">
|
||||||
|
<div class="row">
|
||||||
|
<div class="span11">
|
||||||
|
<i class="icon-chevron-right x-expander expander pull-left"/>
|
||||||
|
|
||||||
|
<span class="title span5">
|
||||||
|
<a href="{{route}}">
|
||||||
|
{{title}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
<select class="x-season-select season-select">
|
||||||
|
<option value="-1">Select season...</option>
|
||||||
|
{{#each seasons.models}}
|
||||||
|
{{#if_eq attributes.seasonNumber compare="0"}}
|
||||||
|
<option value="{{attributes.seasonumber}}">Specials</option>
|
||||||
|
{{else}}
|
||||||
|
<option value="{{attributes.seasonNumber}}">Season {{attributes.seasonNumber}}</option>
|
||||||
|
{{/if_eq}}
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
<span class="help-inline">
|
||||||
|
<i class="icon-question-sign" title="Selecting a season will unmonitor all previous seasons"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="span11">
|
||||||
|
<div class="x-season-grid season-grid"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,24 +1,25 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'Series/SeasonModel',
|
'backbone',
|
||||||
'backbone.pageable'
|
'Series/SeasonModel'
|
||||||
], function (SeasonModel, PageAbleCollection) {
|
], function (Backbone, SeasonModel) {
|
||||||
return PageAbleCollection.extend({
|
return Backbone.Collection.extend({
|
||||||
url : window.ApiRoot + '/season',
|
url : window.ApiRoot + '/season',
|
||||||
model: SeasonModel,
|
model: SeasonModel,
|
||||||
|
|
||||||
mode: 'client',
|
comparator: function (season) {
|
||||||
|
return -season.get('seasonNumber');
|
||||||
state: {
|
|
||||||
sortKey : 'seasonNumber',
|
|
||||||
order : 1,
|
|
||||||
pageSize: 1000000
|
|
||||||
},
|
},
|
||||||
|
|
||||||
queryParams: {
|
bySeries: function (series) {
|
||||||
sortKey: null,
|
var filtered = this.filter(function (season) {
|
||||||
order : null
|
return season.get('seriesId') === series;
|
||||||
|
});
|
||||||
|
|
||||||
|
var SeasonCollection = require('Series/SeasonCollection');
|
||||||
|
|
||||||
|
return new SeasonCollection(filtered);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -247,3 +247,29 @@
|
||||||
.series-legend {
|
.series-legend {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.seasonpass-series {
|
||||||
|
.card;
|
||||||
|
margin : 20px 0px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 30px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.season-select {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expander {
|
||||||
|
.clickable;
|
||||||
|
line-height: 30px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.season-grid {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue