this should cover it!

This commit is contained in:
Keivan Beigi 2013-09-11 17:42:15 -07:00
parent 7f5136120d
commit c090b3efa1
15 changed files with 166 additions and 331 deletions

View File

@ -5,6 +5,14 @@ namespace NzbDrone.Core.Notifications.Email
{ {
public class TestEmailCommand : Command public class TestEmailCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string Server { get; set; } public string Server { get; set; }
public int Port { get; set; } public int Port { get; set; }
public bool Ssl { get; set; } public bool Ssl { get; set; }

View File

@ -7,6 +7,13 @@ namespace NzbDrone.Core.Notifications.Growl
{ {
public class TestGrowlCommand : Command public class TestGrowlCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string Host { get; set; } public string Host { get; set; }
public int Port { get; set; } public int Port { get; set; }
public string Password { get; set; } public string Password { get; set; }

View File

@ -7,6 +7,13 @@ namespace NzbDrone.Core.Notifications.Plex
{ {
public class TestPlexClientCommand : Command public class TestPlexClientCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string Host { get; set; } public string Host { get; set; }
public int Port { get; set; } public int Port { get; set; }
public string Username { get; set; } public string Username { get; set; }

View File

@ -7,6 +7,14 @@ namespace NzbDrone.Core.Notifications.Plex
{ {
public class TestPlexServerCommand : Command public class TestPlexServerCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string Host { get; set; } public string Host { get; set; }
public int Port { get; set; } public int Port { get; set; }
} }

View File

@ -7,6 +7,13 @@ namespace NzbDrone.Core.Notifications.Prowl
{ {
public class TestProwlCommand : Command public class TestProwlCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string ApiKey { get; set; } public string ApiKey { get; set; }
public int Priority { get; set; } public int Priority { get; set; }
} }

View File

@ -7,6 +7,14 @@ namespace NzbDrone.Core.Notifications.Pushover
{ {
public class TestPushoverCommand : Command public class TestPushoverCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string UserKey { get; set; } public string UserKey { get; set; }
public int Priority { get; set; } public int Priority { get; set; }
} }

View File

@ -7,6 +7,14 @@ namespace NzbDrone.Core.Notifications.Xbmc
{ {
public class TestXbmcCommand : Command public class TestXbmcCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
public string Host { get; set; } public string Host { get; set; }
public int Port { get; set; } public int Port { get; set; }
public string Username { get; set; } public string Username { get; set; }

View File

@ -3,10 +3,12 @@ define(
[ [
'Commands/CommandModel', 'Commands/CommandModel',
'Commands/CommandCollection', 'Commands/CommandCollection',
'underscore' 'underscore',
'jQuery/jquery.spin'
], function (CommandModel, CommandCollection, _) { ], function (CommandModel, CommandCollection, _) {
return{ return{
Execute: function (name, properties) { Execute: function (name, properties) {
var attr = _.extend({name: name.toLocaleLowerCase()}, properties); var attr = _.extend({name: name.toLocaleLowerCase()}, properties);
@ -16,6 +18,39 @@ define(
return commandModel.save().success(function () { return commandModel.save().success(function () {
CommandCollection.add(commandModel); CommandCollection.add(commandModel);
}); });
},
bindToCommand: function (options) {
var self = this;
var existingCommand = CommandCollection.findCommand(options.command);
if (existingCommand) {
this._bindToCommandModel.call(this, existingCommand, options);
}
CommandCollection.bind('add sync', function (model) {
if (model.isSameCommand(options.command)) {
self._bindToCommandModel.call(self, model, options);
}
});
},
_bindToCommandModel: function bindToCommand(model, options) {
if (!model.isActive()) {
options.element.stopSpin();
return;
}
model.bind('change:state', function (model) {
if (!model.isActive()) {
options.element.stopSpin();
}
});
options.element.startSpin();
} }
} }
}); });

View File

@ -7,11 +7,10 @@ require(
'Series/SeriesCollection', 'Series/SeriesCollection',
'ProgressMessaging/ProgressMessageCollection', 'ProgressMessaging/ProgressMessageCollection',
'Commands/CommandMessengerCollectionView', 'Commands/CommandMessengerCollectionView',
'Shared/Actioneer',
'Navbar/NavbarView', 'Navbar/NavbarView',
'jQuery/RouteBinder', 'jQuery/RouteBinder',
'jquery' 'jquery'
], function (App, Marionette, Controller, SeriesCollection, ProgressMessageCollection, CommandMessengerCollectionView, Actioneer, NavbarView, RouterBinder, $) { ], function (App, Marionette, Controller, SeriesCollection, ProgressMessageCollection, CommandMessengerCollectionView, NavbarView, RouterBinder, $) {
var Router = Marionette.AppRouter.extend({ var Router = Marionette.AppRouter.extend({

View File

@ -2,9 +2,9 @@
define( define(
[ [
'marionette', 'marionette',
'Series/SeasonCollection', 'backgrid',
'Cells/ToggleCell' 'Series/SeasonCollection'
], function (Marionette, Backgrid, SeasonCollection, ToggleCell) { ], function (Marionette, Backgrid, SeasonCollection) {
return Marionette.Layout.extend({ return Marionette.Layout.extend({
template: 'SeasonPass/SeriesLayoutTemplate', template: 'SeasonPass/SeriesLayoutTemplate',
@ -111,11 +111,9 @@ define(
this.model.setSeasonMonitored(seasonNumber); this.model.setSeasonMonitored(seasonNumber);
Actioneer.SaveModel({ var savePromise =this.model.save()
element: element, .always(this.render.bind(this));
context: this, element.spinForPromise(savePromise);
always : this._afterToggleSeasonMonitored
});
}, },
_afterToggleSeasonMonitored: function () { _afterToggleSeasonMonitored: function () {

View File

@ -8,9 +8,9 @@ define(
'Cells/EpisodeTitleCell', 'Cells/EpisodeTitleCell',
'Cells/RelativeDateCell', 'Cells/RelativeDateCell',
'Cells/EpisodeStatusCell', 'Cells/EpisodeStatusCell',
'Shared/Actioneer', 'Commands/CommandController',
'moment' 'moment'
], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer, Moment) { ], function (App, Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Moment) {
return Marionette.Layout.extend({ return Marionette.Layout.extend({
template: 'Series/Details/SeasonLayoutTemplate', template: 'Series/Details/SeasonLayoutTemplate',
@ -21,11 +21,11 @@ define(
}, },
events: { events: {
'click .x-season-search' : '_seasonSearch', 'click .x-season-monitored' : '_seasonMonitored',
'click .x-season-monitored' : '_seasonMonitored', 'click .x-season-search' : '_seasonSearch',
'click .x-season-rename' : '_seasonRename', 'click .x-season-rename' : '_seasonRename',
'click .x-show-hide-episodes' : '_showHideEpisodes', 'click .x-show-hide-episodes': '_showHideEpisodes',
'dblclick .series-season h2' : '_showHideEpisodes' 'dblclick .series-season h2' : '_showHideEpisodes'
}, },
regions: { regions: {
@ -51,11 +51,11 @@ define(
}) })
}, },
{ {
name : 'this', name : 'this',
label : 'Title', label : 'Title',
hideSeriesLink : true, hideSeriesLink: true,
cell : EpisodeTitleCell, cell : EpisodeTitleCell,
sortable: false sortable : false
}, },
{ {
name : 'airDateUtc', name : 'airDateUtc',
@ -75,42 +75,60 @@ define(
if (!options.episodeCollection) { if (!options.episodeCollection) {
throw 'episodeCollection is needed'; throw 'episodeCollection is needed';
} }
this.templateHelpers = this.templateHelpers || {};
this.templateHelpers = {};
this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber')); this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber'));
this.series = options.series; this.series = options.series;
this.showingEpisodes = this._shouldShowEpisodes(); this.showingEpisodes = this._shouldShowEpisodes();
this._generateTemplateHelpers();
this.listenTo(this.model, 'sync', function () { this.listenTo(this.model, 'sync', this._afterSeasonMonitored);
this._afterSeasonMonitored(); this.listenTo(this.episodeCollection, 'sync', this.render);
}, this);
this.listenTo(this.episodeCollection, 'sync', function () {
this.render();
}, this);
}, },
onRender: function () { onRender: function () {
this._generateTemplateHelpers();
if (this.showingEpisodes) { if (this.showingEpisodes) {
this._showEpisodes(); this._showEpisodes();
} }
this._setSeasonMonitoredState(); this._setSeasonMonitoredState();
CommandController.bindToCommand({
element: this.ui.seasonSearch,
command: {
name: 'seasonSearch',
seriesId : this.series.id,
seasonNumber: this.model.get('seasonNumber')
}
});
CommandController.bindToCommand({
element: this.ui.seasonRename,
command: {
name: 'renameSeason',
seriesId : this.series.id,
seasonNumber: this.model.get('seasonNumber')
}
});
}, },
_seasonSearch: function () { _seasonSearch: function () {
Actioneer.ExecuteCommand({
command : 'seasonSearch', CommandController.Execute('seasonSearch', {
properties : { name: 'seasonSearch',
seriesId : this.model.get('seriesId'), seriesId : this.series.id,
seasonNumber: this.model.get('seasonNumber') seasonNumber: this.model.get('seasonNumber')
}, });
element : this.ui.seasonSearch, },
errorMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')),
startMessage : 'Search for season {0} started'.format(this.model.get('seasonNumber')), _seasonRename: function () {
successMessage: 'Search for season {0} completed'.format(this.model.get('seasonNumber'))
CommandController.Execute('renameSeason', {
name: 'renameSeason',
seriesId : this.series.id,
seasonNumber: this.model.get('seasonNumber')
}); });
}, },
@ -119,12 +137,10 @@ define(
this.model.set(name, !this.model.get(name)); this.model.set(name, !this.model.get(name));
this.series.setSeasonMonitored(this.model.get('seasonNumber')); this.series.setSeasonMonitored(this.model.get('seasonNumber'));
Actioneer.SaveModel({ var savePromise = this.series.save()
model : this.series, .always(this._afterSeasonMonitored.bind(this));
context: this,
element: this.ui.seasonMonitored, this.ui.seasonMonitored.spinForPromise(savePromise);
always : this._afterSeasonMonitored
});
}, },
_afterSeasonMonitored: function () { _afterSeasonMonitored: function () {
@ -150,19 +166,7 @@ define(
} }
}, },
_seasonRename: function () {
Actioneer.ExecuteCommand({
command : 'renameSeason',
properties : {
seriesId : this.model.get('seriesId'),
seasonNumber: this.model.get('seasonNumber')
},
element : this.ui.seasonRename,
errorMessage: 'Season rename failed',
context : this,
onSuccess : this._afterRename
});
},
_afterRename: function () { _afterRename: function () {
App.vent.trigger(App.Events.SeasonRenamed, { series: this.series, seasonNumber: this.model.get('seasonNumber') }); App.vent.trigger(App.Events.SeasonRenamed, { series: this.series, seasonNumber: this.model.get('seasonNumber') });
@ -180,12 +184,11 @@ define(
var startDate = Moment().add('month', -1); var startDate = Moment().add('month', -1);
var endDate = Moment().add('year', 1); var endDate = Moment().add('year', 1);
var result = this.episodeCollection.some(function(episode) { var result = this.episodeCollection.some(function (episode) {
var airDate = episode.get('airDateUtc'); var airDate = episode.get('airDateUtc');
if (airDate) if (airDate) {
{
var airDateMoment = Moment(airDate); var airDateMoment = Moment(airDate);
if (airDateMoment.isAfter(startDate) && airDateMoment.isBefore(endDate)) { if (airDateMoment.isAfter(startDate) && airDateMoment.isBefore(endDate)) {
@ -203,7 +206,7 @@ define(
this.templateHelpers.showingEpisodes = this.showingEpisodes; this.templateHelpers.showingEpisodes = this.showingEpisodes;
var episodeCount = this.episodeCollection.filter(function (episode) { var episodeCount = this.episodeCollection.filter(function (episode) {
return (episode.get('monitored') && Moment(episode.get('airDateUtc')).isBefore(Moment())) || episode.get('hasFile'); return (episode.get('monitored') && Moment(episode.get('airDateUtc')).isBefore(Moment())) || episode.get('hasFile');
}).length; }).length;
var episodeFileCount = this.episodeCollection.where({ hasFile: true }).length; var episodeFileCount = this.episodeCollection.where({ hasFile: true }).length;
@ -221,14 +224,11 @@ define(
_showHideEpisodes: function () { _showHideEpisodes: function () {
if (this.showingEpisodes) { if (this.showingEpisodes) {
this.showingEpisodes = false; this.showingEpisodes = false;
this.episodeGrid.$el.slideUp();
this.episodeGrid.close(); this.episodeGrid.close();
} }
else { else {
this.showingEpisodes = true; this.showingEpisodes = true;
this._showEpisodes(); this._showEpisodes();
this.episodeGrid.$el.slideDown();
} }
this.templateHelpers.showingEpisodes = this.showingEpisodes; this.templateHelpers.showingEpisodes = this.showingEpisodes;

View File

@ -10,10 +10,9 @@ define(
'Series/Details/InfoView', 'Series/Details/InfoView',
'Commands/CommandController', 'Commands/CommandController',
'Shared/LoadingView', 'Shared/LoadingView',
'Shared/Actioneer',
'backstrech', 'backstrech',
'Mixins/backbone.signalr.mixin' 'Mixins/backbone.signalr.mixin'
], function (App, Marionette, EpisodeCollection, EpisodeFileCollection, SeasonCollection, SeasonCollectionView, InfoView, CommandController, LoadingView, Actioneer) { ], function (App, Marionette, EpisodeCollection, EpisodeFileCollection, SeasonCollection, SeasonCollectionView, InfoView, CommandController, LoadingView) {
return Marionette.Layout.extend({ return Marionette.Layout.extend({
itemViewContainer: '.x-series-seasons', itemViewContainer: '.x-series-seasons',
@ -67,21 +66,21 @@ define(
}, },
onRender: function () { onRender: function () {
Actioneer.bindToCommand({ CommandController.bindToCommand({
element: this.ui.refresh, element: this.ui.refresh,
command: { command: {
name: 'refreshSeries' name: 'refreshSeries'
} }
}); });
Actioneer.bindToCommand({ CommandController.bindToCommand({
element: this.ui.search, element: this.ui.search,
command: { command: {
name: 'seriesSearch' name: 'seriesSearch'
} }
}); });
Actioneer.bindToCommand({ CommandController.bindToCommand({
element: this.ui.rename, element: this.ui.rename,
command: { command: {
name: 'renameSeries' name: 'renameSeries'
@ -195,13 +194,9 @@ define(
this.info.show(new InfoView({ model: this.model })); this.info.show(new InfoView({ model: this.model }));
}, },
_refetchEpisodeFiles: function () {
this.episodeFileCollection.fetch();
},
_onSeasonRenamed: function (event) { _onSeasonRenamed: function (event) {
if (this.model.get('id') === event.series.get('id')) { if (this.model.get('id') === event.series.get('id')) {
this._refetchEpisodeFiles(); this.episodeFileCollection.fetch();
} }
} }
}); });

View File

@ -6,11 +6,11 @@ define([
'Settings/Notifications/Model', 'Settings/Notifications/Model',
'Settings/Notifications/DeleteView', 'Settings/Notifications/DeleteView',
'Shared/Messenger', 'Shared/Messenger',
'Shared/Actioneer', 'Commands/CommandController',
'Mixins/AsModelBoundView', 'Mixins/AsModelBoundView',
'Form/FormBuilder' 'Form/FormBuilder'
], function (App, Marionette, NotificationModel, DeleteView, Messenger, Actioneer, AsModelBoundView) { ], function (App, Marionette, NotificationModel, DeleteView, Messenger, CommandController, AsModelBoundView) {
var model = Marionette.ItemView.extend({ var model = Marionette.ItemView.extend({
template: 'Settings/Notifications/EditTemplate', template: 'Settings/Notifications/EditTemplate',
@ -76,16 +76,8 @@ define([
properties[field.name] = field.value; properties[field.name] = field.value;
}); });
Actioneer.ExecuteCommand({
command : testCommand, CommandController.Execute(testCommand, properties);
properties : properties,
button : this.ui.testButton,
element : this.ui.testIcon,
errorMessage : 'Failed to test notification settings',
successMessage: 'Notification settings tested successfully',
always : this._testOnAlways,
context : this
});
} }
}, },

View File

@ -1,236 +0,0 @@
'use strict';
define(
[
'Commands/CommandController',
'Commands/CommandCollection',
'Shared/Messenger',
'jQuery/jquery.spin'
], function (CommandController, CommandCollection, Messenger) {
var actioneer = Marionette.AppRouter.extend({
initialize: function () {
this.trackedCommands =
[
];
CommandCollection.fetch();
this.listenTo(CommandCollection, 'sync', this._handleCommands);
},
bindToCommand: function (options) {
var self = this;
options.idleIcon = this._getIconClass(options.element);
var existingCommand = CommandCollection.findCommand(options.command);
if (existingCommand) {
this._bindToCommandModel.call(this, existingCommand, options);
}
this.listenTo(CommandCollection, 'add sync', function (model) {
if (model.isSameCommand(options.command)) {
self._bindToCommandModel.call(self, model, options);
}
});
},
_bindToCommandModel: function bindToCommand(model, options) {
if (!model.isActive()) {
options.element.stopSpin();
return;
}
this.listenTo(model, 'change:state', function (model) {
if (!model.isActive()) {
options.element.stopSpin();
}
});
options.element.startSpin();
},
ExecuteCommand: function (options) {
options.iconClass = this._getIconClass(options.element);
if (options.button) {
options.button.addClass('disable');
}
this._setSpinnerOnElement(options);
var promise = CommandController.Execute(options.command, options.properties);
this._showStartMessage(options, promise);
},
SaveModel: function (options) {
options.iconClass = this._getIconClass(options.element);
this._showStartMessage(options);
this._setSpinnerOnElement(options);
var model = options.model ? options.model : options.context.model;
var promise = model.save();
this._handlePromise(promise, options);
},
_handlePromise: function (promise, options) {
var self = this;
promise.done(function () {
self._onSuccess(options);
});
promise.fail(function (ajaxOptions) {
if (ajaxOptions.readyState === 0 || ajaxOptions.status === 0) {
return;
}
self._onError(options);
});
promise.always(function () {
self._onComplete(options);
});
},
_handleCommands: function () {
var self = this;
_.each(this.trackedCommands, function (trackedCommand) {
if (trackedCommand.completed === true) {
return;
}
var options = trackedCommand.options;
var command = CommandCollection.find({ 'id': trackedCommand.id });
if (!command) {
trackedCommand.completed = true;
self._onError(options, trackedCommand.id);
self._onComplete(options);
return;
}
if (command.get('state') === 'completed') {
trackedCommand.completed = true;
self._onSuccess(options, command.get('id'));
self._onComplete(options);
return;
}
if (command.get('state') === 'failed') {
trackedCommand.completed = true;
self._onError(options, command.get('id'));
self._onComplete(options);
}
});
},
_getIconClass: function (element) {
if (!element) {
return '';
}
return element.find('i').attr('class').match(/(?:^|\s)icon\-.+?(?:$|\s)/)[0];
},
_setSpinnerOnElement: function (options) {
if (!options.element) {
return;
}
if (options.leaveIcon) {
options.element.addClass('icon-spin');
}
else {
options.element.removeClass(options.iconClass);
options.element.addClass('icon-nd-spinner');
}
},
_onSuccess: function (options, id) {
if (options.successMessage) {
Messenger.show({
id : id,
message: options.successMessage,
type : 'success'
});
}
if (options.onSuccess) {
options.onSuccess.call(options.context);
}
},
_onError: function (options, id) {
if (options.errorMessage) {
Messenger.show({
id : id,
message: options.errorMessage,
type : 'error'
});
}
if (options.onError) {
options.onError.call(options.context);
}
},
_onComplete: function (options) {
if (options.button) {
options.button.removeClass('disable');
}
if (options.element) {
if (options.leaveIcon) {
options.element.removeClass('icon-spin');
}
else {
options.element.addClass(options.iconClass);
options.element.removeClass('icon-nd-spinner');
options.element.removeClass('icon-spin');
}
}
if (options.always) {
options.always.call(options.context);
}
},
_showStartMessage: function (options, promise) {
var self = this;
if (!promise) {
if (options.startMessage) {
Messenger.show({
message: options.startMessage
});
}
return;
}
promise.done(function (data) {
self.trackedCommands.push({ id: data.id, options: options });
if (options.startMessage) {
Messenger.show({
id : data.id,
message: options.startMessage
});
}
});
}
});
return new actioneer();
});

View File

@ -3,9 +3,8 @@ define(
[ [
'app', 'app',
'marionette', 'marionette',
'Commands/CommandController', 'Commands/CommandController'
'Shared/Actioneer' ], function (App, Marionette, CommandController) {
], function (App, Marionette, CommandController, Actioneer) {
return Marionette.ItemView.extend({ return Marionette.ItemView.extend({
template : 'Shared/Toolbar/ButtonTemplate', template : 'Shared/Toolbar/ButtonTemplate',
@ -31,7 +30,7 @@ define(
var command = this.model.get('command'); var command = this.model.get('command');
if (command) { if (command) {
Actioneer.bindToCommand({ CommandController.bindToCommand({
command: {name: command}, command: {name: command},
element: this.$el element: this.$el
}); });