mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Commands return immediately and signalr is used to control the UI
This commit is contained in:
parent
772ab3c921
commit
c96ba5efd3
42
NzbDrone.Api/Commands/CommandConnection.cs
Normal file
42
NzbDrone.Api/Commands/CommandConnection.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Microsoft.AspNet.SignalR;
|
||||
using Microsoft.AspNet.SignalR.Infrastructure;
|
||||
using NzbDrone.Api.SignalR;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Common.Messaging.Events;
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Api.Commands
|
||||
{
|
||||
public class CommandConnection : NzbDronePersistentConnection,
|
||||
IHandleAsync<CommandStartedEvent>,
|
||||
IHandleAsync<CommandCompletedEvent>,
|
||||
IHandle<CommandFailedEvent>
|
||||
{
|
||||
public override string Resource
|
||||
{
|
||||
get { return "/Command"; }
|
||||
}
|
||||
|
||||
public void HandleAsync(CommandStartedEvent message)
|
||||
{
|
||||
BroadcastMessage(message.Command);
|
||||
}
|
||||
|
||||
public void HandleAsync(CommandCompletedEvent message)
|
||||
{
|
||||
BroadcastMessage(message.Command);
|
||||
}
|
||||
|
||||
public void Handle(CommandFailedEvent message)
|
||||
{
|
||||
BroadcastMessage(message.Command);
|
||||
}
|
||||
|
||||
private void BroadcastMessage(TrackedCommand trackedCommand)
|
||||
{
|
||||
var context = ((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType());
|
||||
context.Connection.Broadcast(trackedCommand);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Mapping;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
@ -32,9 +33,10 @@ private Response RunCommand(CommandResource resource)
|
||||
.Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
dynamic command = Request.Body.FromJson(commandType);
|
||||
_messageAggregator.PublishCommand(command);
|
||||
|
||||
return resource.AsResponse(HttpStatusCode.Created);
|
||||
var response = (TrackedCommand) _messageAggregator.PublishCommandAsync(command);
|
||||
|
||||
return response.AsResponse(HttpStatusCode.Created);
|
||||
}
|
||||
|
||||
private Response GetAllCommands()
|
||||
|
@ -12,7 +12,6 @@ public static class ReqResExtensions
|
||||
{
|
||||
private static readonly NancyJsonSerializer NancySerializer = new NancyJsonSerializer();
|
||||
|
||||
|
||||
public static readonly string LastModified = BuildInfo.BuildDateTime.ToString("r");
|
||||
|
||||
public static T FromJson<T>(this Stream body) where T : class, new()
|
||||
@ -25,7 +24,6 @@ public static T FromJson<T>(this Stream body, Type type)
|
||||
return (T)FromJson(body, type);
|
||||
}
|
||||
|
||||
|
||||
public static object FromJson(this Stream body, Type type)
|
||||
{
|
||||
var reader = new StreamReader(body, true);
|
||||
|
@ -83,6 +83,7 @@
|
||||
<Compile Include="ClientSchema\SelectOption.cs" />
|
||||
<Compile Include="Commands\CommandModule.cs" />
|
||||
<Compile Include="Commands\CommandResource.cs" />
|
||||
<Compile Include="Commands\CommandConnection.cs" />
|
||||
<Compile Include="Config\NamingConfigResource.cs" />
|
||||
<Compile Include="Config\NamingModule.cs" />
|
||||
<Compile Include="EpisodeFiles\EpisodeFileModule.cs" />
|
||||
|
@ -76,7 +76,7 @@ public void broken_executor_should_throw_the_exception()
|
||||
|
||||
public class CommandA : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
public CommandA(int id = 0)
|
||||
// ReSharper restore UnusedParameter.Local
|
||||
@ -87,7 +87,7 @@ public CommandA(int id = 0)
|
||||
|
||||
public class CommandB : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public CommandB()
|
||||
{
|
||||
|
@ -1,10 +1,12 @@
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
{
|
||||
public class CommandCompletedEvent : IEvent
|
||||
{
|
||||
public ICommand Command { get; private set; }
|
||||
public TrackedCommand Command { get; private set; }
|
||||
|
||||
public CommandCompletedEvent(ICommand command)
|
||||
public CommandCompletedEvent(TrackedCommand command)
|
||||
{
|
||||
Command = command;
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
{
|
||||
public class CommandExecutedEvent : IEvent
|
||||
{
|
||||
public ICommand Command { get; private set; }
|
||||
public TrackedCommand Command { get; private set; }
|
||||
|
||||
public CommandExecutedEvent(ICommand command)
|
||||
public CommandExecutedEvent(TrackedCommand command)
|
||||
{
|
||||
Command = command;
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
{
|
||||
public class CommandFailedEvent : IEvent
|
||||
{
|
||||
public ICommand Command { get; private set; }
|
||||
public TrackedCommand Command { get; private set; }
|
||||
public Exception Exception { get; private set; }
|
||||
|
||||
public CommandFailedEvent(ICommand command, Exception exception)
|
||||
public CommandFailedEvent(TrackedCommand command, Exception exception)
|
||||
{
|
||||
Command = command;
|
||||
Exception = exception;
|
||||
|
@ -1,10 +1,12 @@
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Events
|
||||
{
|
||||
public class CommandStartedEvent : IEvent
|
||||
{
|
||||
public ICommand Command { get; private set; }
|
||||
public TrackedCommand Command { get; private set; }
|
||||
|
||||
public CommandStartedEvent(ICommand command)
|
||||
public CommandStartedEvent(TrackedCommand command)
|
||||
{
|
||||
Command = command;
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace NzbDrone.Common.Messaging
|
||||
using NzbDrone.Common.Messaging.Tracking;
|
||||
|
||||
namespace NzbDrone.Common.Messaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables loosely-coupled publication of events.
|
||||
@ -7,6 +9,8 @@ public interface IMessageAggregator
|
||||
{
|
||||
void PublishEvent<TEvent>(TEvent @event) where TEvent : class, IEvent;
|
||||
void PublishCommand<TCommand>(TCommand command) where TCommand : class, ICommand;
|
||||
void PublishCommand(string commandType);
|
||||
void PublishCommand(string commandTypeName);
|
||||
TrackedCommand PublishCommandAsync<TCommand>(TCommand command) where TCommand : class, ICommand;
|
||||
TrackedCommand PublishCommandAsync(string commandTypeName);
|
||||
}
|
||||
}
|
@ -78,61 +78,94 @@ public void PublishCommand<TCommand>(TCommand command) where TCommand : class, I
|
||||
{
|
||||
Ensure.That(() => command).IsNotNull();
|
||||
|
||||
var handlerContract = typeof(IExecute<>).MakeGenericType(command.GetType());
|
||||
_logger.Trace("Publishing {0}", command.GetType().Name);
|
||||
|
||||
var trackedCommand = _trackCommands.TrackIfNew(command);
|
||||
|
||||
if (trackedCommand == null)
|
||||
{
|
||||
_logger.Info("Command is already in progress: {0}", command.GetType().Name);
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteCommand<TCommand>(trackedCommand);
|
||||
}
|
||||
|
||||
public void PublishCommand(string commandTypeName)
|
||||
{
|
||||
dynamic command = GetCommand(commandTypeName);
|
||||
PublishCommand(command);
|
||||
}
|
||||
|
||||
public TrackedCommand PublishCommandAsync<TCommand>(TCommand command) where TCommand : class, ICommand
|
||||
{
|
||||
Ensure.That(() => command).IsNotNull();
|
||||
|
||||
_logger.Trace("Publishing {0}", command.GetType().Name);
|
||||
|
||||
var existingCommand = _trackCommands.TrackNewOrGet(command);
|
||||
|
||||
if (existingCommand.Existing)
|
||||
{
|
||||
_logger.Info("Command is already in progress: {0}", command.GetType().Name);
|
||||
return existingCommand.TrackedCommand;
|
||||
}
|
||||
|
||||
_taskFactory.StartNew(() => ExecuteCommand<TCommand>(existingCommand.TrackedCommand)
|
||||
, TaskCreationOptions.PreferFairness)
|
||||
.LogExceptions();
|
||||
|
||||
return existingCommand.TrackedCommand;
|
||||
}
|
||||
|
||||
public TrackedCommand PublishCommandAsync(string commandTypeName)
|
||||
{
|
||||
dynamic command = GetCommand(commandTypeName);
|
||||
return PublishCommandAsync(command);
|
||||
}
|
||||
|
||||
private dynamic GetCommand(string commandTypeName)
|
||||
{
|
||||
var commandType = _serviceFactory.GetImplementations(typeof(ICommand))
|
||||
.Single(c => c.FullName.Equals(commandTypeName, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
return Json.Deserialize("{}", commandType);
|
||||
}
|
||||
|
||||
private void ExecuteCommand<TCommand>(TrackedCommand trackedCommand) where TCommand : class, ICommand
|
||||
{
|
||||
var command = (TCommand)trackedCommand.Command;
|
||||
|
||||
var handlerContract = typeof(IExecute<>).MakeGenericType(command.GetType());
|
||||
var handler = (IExecute<TCommand>)_serviceFactory.Build(handlerContract);
|
||||
|
||||
_logger.Debug("{0} -> {1}", command.GetType().Name, handler.GetType().Name);
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
TrackedCommand trackedCommand = null;
|
||||
|
||||
try
|
||||
{
|
||||
trackedCommand = _trackCommands.TrackIfNew(command);
|
||||
|
||||
if (trackedCommand == null)
|
||||
{
|
||||
_logger.Info("Command is already in progress: {0}", command.GetType().Name);
|
||||
return;
|
||||
}
|
||||
|
||||
MappedDiagnosticsContext.Set("CommandId", trackedCommand.Command.CommandId);
|
||||
|
||||
PublishEvent(new CommandStartedEvent(command));
|
||||
PublishEvent(new CommandStartedEvent(trackedCommand));
|
||||
handler.Execute(command);
|
||||
sw.Stop();
|
||||
|
||||
_trackCommands.Completed(trackedCommand, sw.Elapsed);
|
||||
PublishEvent(new CommandCompletedEvent(command));
|
||||
PublishEvent(new CommandCompletedEvent(trackedCommand));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (trackedCommand != null)
|
||||
{
|
||||
_trackCommands.Failed(trackedCommand, e);
|
||||
}
|
||||
|
||||
PublishEvent(new CommandFailedEvent(command, e));
|
||||
_trackCommands.Failed(trackedCommand, e);
|
||||
PublishEvent(new CommandFailedEvent(trackedCommand, e));
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
PublishEvent(new CommandExecutedEvent(command));
|
||||
PublishEvent(new CommandExecutedEvent(trackedCommand));
|
||||
}
|
||||
|
||||
_logger.Debug("{0} <- {1} [{2}]", command.GetType().Name, handler.GetType().Name, sw.Elapsed.ToString(""));
|
||||
}
|
||||
|
||||
public void PublishCommand(string commandTypeName)
|
||||
{
|
||||
var commandType = _serviceFactory.GetImplementations(typeof(ICommand))
|
||||
.Single(c => c.FullName.Equals(commandTypeName, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
dynamic command = Json.Deserialize("{}", commandType);
|
||||
PublishCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace NzbDrone.Common.Messaging
|
||||
public class TestCommand : ICommand
|
||||
{
|
||||
public int Duration { get; set; }
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public TestCommand()
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Remoting;
|
||||
using NzbDrone.Common.Cache;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Tracking
|
||||
@ -8,10 +9,12 @@ namespace NzbDrone.Common.Messaging.Tracking
|
||||
public interface ITrackCommands
|
||||
{
|
||||
TrackedCommand TrackIfNew(ICommand command);
|
||||
ExistingCommand TrackNewOrGet(ICommand command);
|
||||
TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime);
|
||||
TrackedCommand Failed(TrackedCommand trackedCommand, Exception e);
|
||||
List<TrackedCommand> AllTracked();
|
||||
Boolean ExistingCommand(ICommand command);
|
||||
TrackedCommand FindExisting(ICommand command);
|
||||
}
|
||||
|
||||
public class TrackCommands : ITrackCommands, IExecute<TrackedCommandCleanupCommand>
|
||||
@ -36,6 +39,21 @@ public TrackedCommand TrackIfNew(ICommand command)
|
||||
return trackedCommand;
|
||||
}
|
||||
|
||||
public ExistingCommand TrackNewOrGet(ICommand command)
|
||||
{
|
||||
var trackedCommand = FindExisting(command);
|
||||
|
||||
if (trackedCommand == null)
|
||||
{
|
||||
trackedCommand = new TrackedCommand(command, CommandState.Running);
|
||||
Store(trackedCommand);
|
||||
|
||||
return new ExistingCommand(false, trackedCommand);
|
||||
}
|
||||
|
||||
return new ExistingCommand(true, trackedCommand);
|
||||
}
|
||||
|
||||
public TrackedCommand Completed(TrackedCommand trackedCommand, TimeSpan runtime)
|
||||
{
|
||||
trackedCommand.StateChangeTime = DateTime.UtcNow;
|
||||
@ -65,11 +83,25 @@ public List<TrackedCommand> AllTracked()
|
||||
|
||||
public bool ExistingCommand(ICommand command)
|
||||
{
|
||||
var running = AllTracked().Where(i => i.Type == command.GetType().FullName && i.State == CommandState.Running);
|
||||
return FindExisting(command) != null;
|
||||
}
|
||||
|
||||
var result = running.Select(r => r.Command).Contains(command, new CommandEqualityComparer());
|
||||
public TrackedCommand FindExisting(ICommand command)
|
||||
{
|
||||
var comparer = new CommandEqualityComparer();
|
||||
return Running(command.GetType()).SingleOrDefault(t => comparer.Equals(t.Command, command));
|
||||
}
|
||||
|
||||
return result;
|
||||
private List<TrackedCommand> Running(Type type = null)
|
||||
{
|
||||
var running = AllTracked().Where(i => i.State == CommandState.Running);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
return running.Where(t => t.Type == type.FullName).ToList();
|
||||
}
|
||||
|
||||
return running.ToList();
|
||||
}
|
||||
|
||||
private void Store(TrackedCommand trackedCommand)
|
||||
@ -84,7 +116,7 @@ private void Store(TrackedCommand trackedCommand)
|
||||
|
||||
public void Execute(TrackedCommandCleanupCommand message)
|
||||
{
|
||||
var old = AllTracked().Where(c => c.StateChangeTime < DateTime.UtcNow.AddMinutes(-15));
|
||||
var old = AllTracked().Where(c => c.State != CommandState.Running && c.StateChangeTime < DateTime.UtcNow.AddMinutes(-5));
|
||||
|
||||
foreach (var trackedCommand in old)
|
||||
{
|
||||
|
19
NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs
Normal file
19
NzbDrone.Common/Messaging/Tracking/ExistingCommand.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Common.Messaging.Tracking
|
||||
{
|
||||
public class ExistingCommand
|
||||
{
|
||||
public Boolean Existing { get; set; }
|
||||
public TrackedCommand TrackedCommand { get; set; }
|
||||
|
||||
public ExistingCommand(Boolean exisitng, TrackedCommand trackedCommand)
|
||||
{
|
||||
Existing = exisitng;
|
||||
TrackedCommand = trackedCommand;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ namespace NzbDrone.Common.Messaging.Tracking
|
||||
{
|
||||
public class TrackedCommand
|
||||
{
|
||||
public String Id { get; private set; }
|
||||
public String Name { get; private set; }
|
||||
public String Type { get; private set; }
|
||||
public ICommand Command { get; private set; }
|
||||
public CommandState State { get; set; }
|
||||
@ -13,6 +15,8 @@ public class TrackedCommand
|
||||
|
||||
public TrackedCommand(ICommand command, CommandState state)
|
||||
{
|
||||
Id = command.CommandId;
|
||||
Name = command.GetType().Name;
|
||||
Type = command.GetType().FullName;
|
||||
Command = command;
|
||||
State = state;
|
||||
|
@ -93,6 +93,7 @@
|
||||
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
|
||||
<Compile Include="Instrumentation\ExceptronTarget.cs" />
|
||||
<Compile Include="Messaging\Tracking\CommandTrackingService.cs" />
|
||||
<Compile Include="Messaging\Tracking\ExistingCommand.cs" />
|
||||
<Compile Include="Messaging\Tracking\TrackedCommand.cs" />
|
||||
<Compile Include="Messaging\Events\CommandStartedEvent.cs" />
|
||||
<Compile Include="Messaging\CommandEqualityComparer.cs" />
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
{
|
||||
public class UpdateSceneMappingCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public UpdateSceneMappingCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class EpisodeSearchCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int EpisodeId { get; set; }
|
||||
|
||||
public EpisodeSearchCommand()
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class SeasonSearchCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
{
|
||||
public class SeriesSearchCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
public SeriesSearchCommand()
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
public class RssSyncCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public RssSyncCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands
|
||||
{
|
||||
public class ClearLogCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public ClearLogCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands
|
||||
{
|
||||
public class DeleteLogFilesCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public DeleteLogFilesCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Instrumentation.Commands
|
||||
{
|
||||
public class TrimLogCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public TrimLogCommand()
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ public void Handle(ApplicationStartedEvent message)
|
||||
new ScheduledTask{ Interval = 1, TypeName = typeof(DownloadedEpisodesScanCommand).FullName},
|
||||
new ScheduledTask{ Interval = 60, TypeName = typeof(ApplicationUpdateCommand).FullName},
|
||||
new ScheduledTask{ Interval = 1*60, TypeName = typeof(TrimLogCommand).FullName},
|
||||
new ScheduledTask{ Interval = 5, TypeName = typeof(TrackedCommandCleanupCommand).FullName}
|
||||
new ScheduledTask{ Interval = 1, TypeName = typeof(TrackedCommandCleanupCommand).FullName}
|
||||
};
|
||||
|
||||
var currentTasks = _scheduledTaskRepository.All();
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class CleanMediaFileDb : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int SeriesId { get; private set; }
|
||||
|
||||
public CleanMediaFileDb()
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class CleanUpRecycleBinCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public CleanUpRecycleBinCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class DownloadedEpisodesScanCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public DownloadedEpisodesScanCommand()
|
||||
{
|
||||
|
@ -6,10 +6,10 @@ namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class RenameSeasonCommand : ICommand
|
||||
{
|
||||
public int SeriesId { get; private set; }
|
||||
public int SeasonNumber { get; private set; }
|
||||
public int SeriesId { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public RenameSeasonCommand()
|
||||
{
|
||||
|
@ -6,8 +6,8 @@ namespace NzbDrone.Core.MediaFiles.Commands
|
||||
{
|
||||
public class RenameSeriesCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public int SeriesId { get; private set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int SeriesId { get; set; }
|
||||
|
||||
public RenameSeriesCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Email
|
||||
{
|
||||
public class TestEmailCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string Server { get; set; }
|
||||
public int Port { get; set; }
|
||||
public bool Ssl { get; set; }
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Growl
|
||||
{
|
||||
public class TestGrowlCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
{
|
||||
public class TestPlexClientCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Plex
|
||||
{
|
||||
public class TestPlexServerCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Prowl
|
||||
{
|
||||
public class TestProwlCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string ApiKey { get; set; }
|
||||
public int Priority { get; set; }
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Pushover
|
||||
{
|
||||
public class TestPushoverCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string UserKey { get; set; }
|
||||
public int Priority { get; set; }
|
||||
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
||||
{
|
||||
public class TestXbmcCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
@ -6,13 +6,12 @@ namespace NzbDrone.Core.Providers
|
||||
{
|
||||
public class UpdateXemMappingsCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public int? SeriesId { get; private set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int? SeriesId { get; set; }
|
||||
|
||||
public UpdateXemMappingsCommand(int? seriesId)
|
||||
{
|
||||
CommandId = HashUtil.GenerateCommandId();
|
||||
|
||||
SeriesId = seriesId;
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ namespace NzbDrone.Core.Tv.Commands
|
||||
{
|
||||
public class RefreshSeriesCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public int? SeriesId { get; private set; }
|
||||
public String CommandId { get; private set; }
|
||||
public int? SeriesId { get; set; }
|
||||
|
||||
public RefreshSeriesCommand()
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.Update.Commands
|
||||
{
|
||||
public class ApplicationUpdateCommand : ICommand
|
||||
{
|
||||
public String CommandId { get; set; }
|
||||
public String CommandId { get; private set; }
|
||||
|
||||
public ApplicationUpdateCommand()
|
||||
{
|
||||
|
17
UI/Commands/CommandCollection.js
Normal file
17
UI/Commands/CommandCollection.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Commands/CommandModel',
|
||||
'Mixins/backbone.signalr.mixin'
|
||||
], function (Backbone, CommandModel) {
|
||||
|
||||
var CommandCollection = Backbone.Collection.extend({
|
||||
url : window.ApiRoot + '/command',
|
||||
model: CommandModel
|
||||
});
|
||||
|
||||
var collection = new CommandCollection().bindSignalR();
|
||||
|
||||
return collection;
|
||||
});
|
8
UI/Commands/CommandModel.js
Normal file
8
UI/Commands/CommandModel.js
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone'
|
||||
], function (Backbone) {
|
||||
return Backbone.Model.extend({
|
||||
});
|
||||
});
|
@ -9,9 +9,9 @@ define(
|
||||
'Series/SeriesCollection',
|
||||
'Shared/LoadingView',
|
||||
'Shared/Messenger',
|
||||
'Commands/CommandController',
|
||||
'Shared/Actioneer',
|
||||
'Shared/FormatHelpers'
|
||||
], function (App, Marionette, ButtonsView, ManualSearchLayout, ReleaseCollection, SeriesCollection, LoadingView, Messenger, CommandController, FormatHelpers) {
|
||||
], function (App, Marionette, ButtonsView, ManualSearchLayout, ReleaseCollection, SeriesCollection, LoadingView, Messenger, Actioneer, FormatHelpers) {
|
||||
|
||||
return Marionette.Layout.extend({
|
||||
template: 'Episode/Search/LayoutTemplate',
|
||||
@ -39,16 +39,19 @@ define(
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
CommandController.Execute('episodeSearch', { episodeId: this.model.get('id') });
|
||||
|
||||
var series = SeriesCollection.get(this.model.get('seriesId'));
|
||||
var seriesTitle = series.get('title');
|
||||
var season = this.model.get('seasonNumber');
|
||||
var episode = this.model.get('episodeNumber');
|
||||
var message = seriesTitle + ' - ' + season + 'x' + FormatHelpers.pad(episode, 2);
|
||||
|
||||
Messenger.show({
|
||||
message: 'Search started for: ' + message
|
||||
Actioneer.ExecuteCommand({
|
||||
command : 'episodeSearch',
|
||||
properties : {
|
||||
episodeId: this.model.get('id')
|
||||
},
|
||||
errorMessage: 'Search failed for: ' + message,
|
||||
startMessage: 'Search started for: ' + message
|
||||
});
|
||||
|
||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||
|
@ -5,10 +5,11 @@ require(
|
||||
'marionette',
|
||||
'Controller',
|
||||
'Series/SeriesCollection',
|
||||
'Shared/Actioneer',
|
||||
'Navbar/NavbarView',
|
||||
'jQuery/RouteBinder',
|
||||
'jquery'
|
||||
], function (App, Marionette, Controller, SeriesCollection, NavbarView, RouterBinder, $) {
|
||||
], function (App, Marionette, Controller, SeriesCollection, Actioneer, NavbarView, RouterBinder, $) {
|
||||
|
||||
var Router = Marionette.AppRouter.extend({
|
||||
|
||||
|
@ -113,6 +113,8 @@ define(
|
||||
},
|
||||
|
||||
_setMonitored: function (seasonNumber) {
|
||||
//TODO: use Actioneer?
|
||||
|
||||
var self = this;
|
||||
|
||||
var promise = $.ajax({
|
||||
|
@ -7,9 +7,8 @@ define(
|
||||
'Cells/EpisodeTitleCell',
|
||||
'Cells/RelativeDateCell',
|
||||
'Cells/EpisodeStatusCell',
|
||||
'Commands/CommandController',
|
||||
'Shared/Actioneer'
|
||||
], function ( Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, CommandController, Actioneer) {
|
||||
], function ( Marionette, Backgrid, ToggleCell, EpisodeTitleCell, RelativeDateCell, EpisodeStatusCell, Actioneer) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'Series/Details/SeasonLayoutTemplate',
|
||||
|
||||
@ -101,9 +100,10 @@ define(
|
||||
seriesId : this.model.get('seriesId'),
|
||||
seasonNumber: this.model.get('seasonNumber')
|
||||
},
|
||||
element : this.ui.seasonSearch,
|
||||
failMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')),
|
||||
startMessage: 'Search for season {0} started'.format(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')),
|
||||
successMessage: 'Search for season {0} completed'.format(this.model.get('seasonNumber'))
|
||||
});
|
||||
},
|
||||
|
||||
@ -143,13 +143,13 @@ define(
|
||||
|
||||
_seasonRename: function () {
|
||||
Actioneer.ExecuteCommand({
|
||||
command : 'renameSeason',
|
||||
properties : {
|
||||
command : 'renameSeason',
|
||||
properties : {
|
||||
seriesId : this.model.get('seriesId'),
|
||||
seasonNumber: this.model.get('seasonNumber')
|
||||
},
|
||||
element : this.ui.seasonRename,
|
||||
failMessage: 'Season rename failed'
|
||||
element : this.ui.seasonRename,
|
||||
errorMessage: 'Season rename failed'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ define(
|
||||
seasonNumber: this.model.get('seasonNumber')
|
||||
},
|
||||
element : this.ui.seasonSearch,
|
||||
failMessage : 'Search for season {0} failed'.format(this.model.get('seasonNumber')),
|
||||
errorMessage: 'Search for season {0} failed'.format(this.model.get('seasonNumber')),
|
||||
startMessage: 'Search for season {0} started'.format(this.model.get('seasonNumber'))
|
||||
});
|
||||
},
|
||||
|
@ -154,10 +154,10 @@ define(
|
||||
properties : {
|
||||
seriesId: this.model.get('id')
|
||||
},
|
||||
element : this.ui.rename,
|
||||
context : this,
|
||||
onSuccess : this._refetchEpisodeFiles,
|
||||
failMessage: 'Series search failed'
|
||||
element : this.ui.rename,
|
||||
context : this,
|
||||
onSuccess : this._refetchEpisodeFiles,
|
||||
errorMessage: 'Series search failed'
|
||||
});
|
||||
},
|
||||
|
||||
@ -168,7 +168,7 @@ define(
|
||||
seriesId: this.model.get('id')
|
||||
},
|
||||
element : this.ui.search,
|
||||
failMessage : 'Series search failed',
|
||||
errorMessage: 'Series search failed',
|
||||
startMessage: 'Search for {0} started'.format(this.model.get('title'))
|
||||
});
|
||||
},
|
||||
|
@ -140,7 +140,6 @@ define(
|
||||
this._fetchCollection();
|
||||
},
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.seriesCollection = SeriesCollection;
|
||||
|
||||
@ -148,7 +147,6 @@ define(
|
||||
this.listenTo(SeriesCollection, 'remove', this._renderView);
|
||||
},
|
||||
|
||||
|
||||
_renderView: function () {
|
||||
|
||||
if (SeriesCollection.length === 0) {
|
||||
@ -164,7 +162,6 @@ define(
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onShow: function () {
|
||||
this._showToolbar();
|
||||
this._renderView();
|
||||
|
@ -66,7 +66,7 @@
|
||||
<button class="btn pull-left x-back">back</button>
|
||||
{{/if}}
|
||||
|
||||
<button class="btn x-test">test <i class="x-test-icon"/></button>
|
||||
<button class="btn x-test">test <i class="x-test-icon icon-nd-test"/></button>
|
||||
<button class="btn" data-dismiss="modal">cancel</button>
|
||||
|
||||
<div class="btn-group">
|
||||
|
@ -6,11 +6,11 @@ define([
|
||||
'Settings/Notifications/Model',
|
||||
'Settings/Notifications/DeleteView',
|
||||
'Shared/Messenger',
|
||||
'Commands/CommandController',
|
||||
'Shared/Actioneer',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Form/FormBuilder'
|
||||
|
||||
], function (App, Marionette, NotificationModel, DeleteView, Messenger, CommandController, AsModelBoundView) {
|
||||
], function (App, Marionette, NotificationModel, DeleteView, Messenger, Actioneer, AsModelBoundView) {
|
||||
|
||||
var model = Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/EditTemplate',
|
||||
@ -70,41 +70,28 @@ define([
|
||||
var testCommand = this.model.get('testCommand');
|
||||
if (testCommand) {
|
||||
this.idle = false;
|
||||
this.ui.testButton.addClass('disabled');
|
||||
this.ui.testIcon.addClass('icon-spinner icon-spin');
|
||||
|
||||
var properties = {};
|
||||
|
||||
_.each(this.model.get('fields'), function (field) {
|
||||
properties[field.name] = field.value;
|
||||
});
|
||||
|
||||
var self = this;
|
||||
var commandPromise = CommandController.Execute(testCommand, properties);
|
||||
commandPromise.done(function () {
|
||||
Messenger.show({
|
||||
message: 'Notification settings tested successfully'
|
||||
});
|
||||
Actioneer.ExecuteCommand({
|
||||
command : testCommand,
|
||||
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
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
commandPromise.fail(function (options) {
|
||||
if (options.readyState === 0 || options.status === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Messenger.show({
|
||||
message: 'Failed to test notification settings',
|
||||
type : 'error'
|
||||
});
|
||||
});
|
||||
|
||||
commandPromise.always(function () {
|
||||
if (!self.isClosed) {
|
||||
self.ui.testButton.removeClass('disabled');
|
||||
self.ui.testIcon.removeClass('icon-spinner icon-spin');
|
||||
self.idle = true;
|
||||
}
|
||||
});
|
||||
_testOnAlways: function () {
|
||||
if (!this.isClosed) {
|
||||
this.idle = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,15 +1,30 @@
|
||||
'use strict';
|
||||
define(['Commands/CommandController', 'Shared/Messenger'],
|
||||
function(CommandController, Messenger) {
|
||||
return {
|
||||
define(
|
||||
[
|
||||
'Commands/CommandController',
|
||||
'Commands/CommandCollection',
|
||||
'Shared/Messenger'],
|
||||
function(CommandController, CommandCollection, Messenger) {
|
||||
|
||||
var actioneer = Marionette.AppRouter.extend({
|
||||
|
||||
initialize: function () {
|
||||
this.trackedCommands = [];
|
||||
CommandCollection.fetch();
|
||||
this.listenTo(CommandCollection, 'sync', this._handleCommands);
|
||||
},
|
||||
|
||||
ExecuteCommand: function (options) {
|
||||
options.iconClass = this._getIconClass(options.element);
|
||||
|
||||
this._showStartMessage(options);
|
||||
if (options.button) {
|
||||
options.button.addClass('disable');
|
||||
}
|
||||
|
||||
this._setSpinnerOnElement(options);
|
||||
|
||||
var promise = CommandController.Execute(options.command, options.properties);
|
||||
this._handlePromise(promise, options);
|
||||
this._showStartMessage(options, promise);
|
||||
},
|
||||
|
||||
SaveModel: function (options) {
|
||||
@ -24,15 +39,7 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||
|
||||
_handlePromise: function (promise, options) {
|
||||
promise.done(function () {
|
||||
if (options.successMessage) {
|
||||
Messenger.show({
|
||||
message: options.successMessage
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onSuccess) {
|
||||
options.onSuccess.call(options.context);
|
||||
}
|
||||
self._onSuccess(options);
|
||||
});
|
||||
|
||||
promise.fail(function (ajaxOptions) {
|
||||
@ -40,31 +47,41 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.failMessage) {
|
||||
Messenger.show({
|
||||
message: options.failMessage,
|
||||
type : 'error'
|
||||
});
|
||||
}
|
||||
|
||||
if (options.onError) {
|
||||
options.onError.call(options.context);
|
||||
}
|
||||
self._onError(options);
|
||||
});
|
||||
|
||||
promise.always(function () {
|
||||
self._onComplete(options);
|
||||
});
|
||||
},
|
||||
|
||||
if (options.leaveIcon) {
|
||||
options.element.removeClass('icon-spin');
|
||||
_handleCommands: function () {
|
||||
var self = this;
|
||||
|
||||
_.each(this.trackedCommands, function (trackedCommand){
|
||||
if (trackedCommand.completed === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
options.element.addClass(options.iconClass);
|
||||
options.element.removeClass('icon-nd-spinner');
|
||||
var options = trackedCommand.options;
|
||||
var command = CommandCollection.find({ 'id': trackedCommand.id });
|
||||
|
||||
if (!command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.always) {
|
||||
options.always.call(options.context);
|
||||
if (command.get('state') === 'completed') {
|
||||
trackedCommand.completed = true;
|
||||
|
||||
self._onSuccess(options, command.get('id'));
|
||||
self._onComplete(options);
|
||||
}
|
||||
|
||||
if (command.get('state') === 'failed') {
|
||||
trackedCommand.completed = true;
|
||||
|
||||
self._onError(options, command.get('id'));
|
||||
self._onComplete(options);
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -74,6 +91,10 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||
},
|
||||
|
||||
_setSpinnerOnElement: function (options) {
|
||||
if (!options.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.leaveIcon) {
|
||||
options.element.addClass('icon-spin');
|
||||
}
|
||||
@ -84,12 +105,79 @@ define(['Commands/CommandController', 'Shared/Messenger'],
|
||||
}
|
||||
},
|
||||
|
||||
_showStartMessage: function (options) {
|
||||
if (options.startMessage) {
|
||||
_onSuccess: function (options, id) {
|
||||
if (options.successMessage) {
|
||||
Messenger.show({
|
||||
message: options.startMessage
|
||||
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.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();
|
||||
});
|
||||
|
@ -13,6 +13,10 @@ define(function () {
|
||||
options.hideAfter = 5;
|
||||
break;
|
||||
|
||||
case 'success':
|
||||
options.hideAfter = 5;
|
||||
break;
|
||||
|
||||
default :
|
||||
options.hideAfter = 0;
|
||||
}
|
||||
@ -22,11 +26,11 @@ define(function () {
|
||||
message : options.message,
|
||||
type : options.type,
|
||||
showCloseButton: true,
|
||||
hideAfter : options.hideAfter
|
||||
hideAfter : options.hideAfter,
|
||||
id : options.id
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
monitor: function (options) {
|
||||
|
||||
if (!options.promise) {
|
||||
|
@ -3,9 +3,9 @@ define(
|
||||
[
|
||||
'app',
|
||||
'marionette',
|
||||
'Commands/CommandController',
|
||||
'Shared/Actioneer',
|
||||
'Shared/Messenger'
|
||||
], function (App, Marionette, CommandController, Messenger) {
|
||||
], function (App, Marionette, Actioneer, Messenger) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template : 'Shared/Toolbar/ButtonTemplate',
|
||||
@ -19,7 +19,6 @@ define(
|
||||
icon: '.x-icon'
|
||||
},
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key');
|
||||
this.idle = true;
|
||||
@ -45,68 +44,19 @@ define(
|
||||
},
|
||||
|
||||
invokeCommand: function () {
|
||||
//TODO: Use Actioneer to handle icon swapping
|
||||
|
||||
var command = this.model.get('command');
|
||||
if (command) {
|
||||
this.idle = false;
|
||||
this.$el.addClass('disabled');
|
||||
this.ui.icon.addClass('icon-spinner icon-spin');
|
||||
|
||||
var self = this;
|
||||
var commandPromise = CommandController.Execute(command);
|
||||
commandPromise.done(function () {
|
||||
if (self.model.get('successMessage')) {
|
||||
Messenger.show({
|
||||
message: self.model.get('successMessage')
|
||||
});
|
||||
}
|
||||
|
||||
if (self.model.get('onSuccess')) {
|
||||
if (!self.model.ownerContext) {
|
||||
throw 'ownerContext must be set.';
|
||||
}
|
||||
|
||||
self.model.get('onSuccess').call(self.model.ownerContext);
|
||||
}
|
||||
Actioneer.ExecuteCommand({
|
||||
command : command,
|
||||
button : this.$el,
|
||||
element : this.ui.icon,
|
||||
errorMessage : this.model.get('errorMessage'),
|
||||
successMessage: this.model.get('successMessage'),
|
||||
always : this._commandAlways,
|
||||
context : this
|
||||
});
|
||||
|
||||
commandPromise.fail(function (options) {
|
||||
if (options.readyState === 0 || options.status === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.model.get('errorMessage')) {
|
||||
Messenger.show({
|
||||
message: self.model.get('errorMessage'),
|
||||
type : 'error'
|
||||
});
|
||||
}
|
||||
|
||||
if (self.model.get('onError')) {
|
||||
if (!self.model.ownerContext) {
|
||||
throw 'ownerContext must be set.';
|
||||
}
|
||||
|
||||
self.model.get('onError').call(self.model.ownerContext);
|
||||
}
|
||||
});
|
||||
|
||||
commandPromise.always(function () {
|
||||
if (!self.isClosed) {
|
||||
self.$el.removeClass('disabled');
|
||||
self.ui.icon.removeClass('icon-spinner icon-spin');
|
||||
self.idle = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (self.model.get('always')) {
|
||||
if (!self.model.ownerContext) {
|
||||
throw 'ownerContext must be set.';
|
||||
}
|
||||
|
||||
self.model.get('always').call(self.model.ownerContext);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -133,8 +83,13 @@ define(
|
||||
if (callback) {
|
||||
callback.call(this.model.ownerContext);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_commandAlways: function () {
|
||||
if (!this.isClosed) {
|
||||
this.idle = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -30,10 +30,8 @@ define(
|
||||
this.left = options.left;
|
||||
this.right = options.right;
|
||||
this.toolbarContext = options.context;
|
||||
|
||||
},
|
||||
|
||||
|
||||
onShow: function () {
|
||||
if (this.left) {
|
||||
_.each(this.left, this._showToolbarLeft, this);
|
||||
@ -51,7 +49,6 @@ define(
|
||||
this._showToolbar(element, index, 'right');
|
||||
},
|
||||
|
||||
|
||||
_showToolbar: function (buttonGroup, index, position) {
|
||||
|
||||
var groupCollection = new ButtonCollection();
|
||||
|
Loading…
Reference in New Issue
Block a user