Added shutdown and restart buttons to system UI

New: Shutdown and restart from UI
Fixed: ctrl+c will shutdown app on mono
This commit is contained in:
Mark McDowall 2014-02-06 21:18:48 -08:00
parent 6ff9c9f61e
commit be9b7284b5
7 changed files with 87 additions and 5 deletions

View File

@ -4,5 +4,12 @@ namespace NzbDrone.Core.Lifecycle.Commands
{ {
public class RestartCommand : Command public class RestartCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
} }
} }

View File

@ -4,5 +4,12 @@ namespace NzbDrone.Core.Lifecycle.Commands
{ {
public class ShutdownCommand : Command public class ShutdownCommand : Command
{ {
public override bool SendUpdatesToClient
{
get
{
return true;
}
}
} }
} }

View File

@ -1,7 +1,9 @@
using System.IO; using System.IO;
using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes; using NzbDrone.Common.Processes;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Lifecycle.Commands; using NzbDrone.Core.Lifecycle.Commands;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@ -16,23 +18,27 @@ namespace NzbDrone.Core.Lifecycle
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IProcessProvider _processProvider; private readonly IProcessProvider _processProvider;
private readonly Logger _logger;
public LifestyleService(IEventAggregator eventAggregator, public LifestyleService(IEventAggregator eventAggregator,
IRuntimeInfo runtimeInfo, IRuntimeInfo runtimeInfo,
IAppFolderInfo appFolderInfo, IAppFolderInfo appFolderInfo,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IProcessProvider processProvider) IProcessProvider processProvider,
Logger logger)
{ {
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_runtimeInfo = runtimeInfo; _runtimeInfo = runtimeInfo;
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_processProvider = processProvider; _processProvider = processProvider;
_logger = logger;
} }
public void Execute(ShutdownCommand message) public void Execute(ShutdownCommand message)
{ {
_logger.ProgressInfo("Shutdown requested, goodbye.");
_eventAggregator.PublishEvent(new ApplicationShutdownRequested()); _eventAggregator.PublishEvent(new ApplicationShutdownRequested());
if (_runtimeInfo.IsWindowsService) if (_runtimeInfo.IsWindowsService)
@ -43,6 +49,7 @@ namespace NzbDrone.Core.Lifecycle
public void Execute(RestartCommand message) public void Execute(RestartCommand message)
{ {
_logger.ProgressInfo("Restart requested, brb.");
_eventAggregator.PublishEvent(new ApplicationShutdownRequested(true)); _eventAggregator.PublishEvent(new ApplicationShutdownRequested(true));
if (_runtimeInfo.IsWindowsService) if (_runtimeInfo.IsWindowsService)

View File

@ -167,3 +167,12 @@
.icon(@cloud-download); .icon(@cloud-download);
color: @errorText; color: @errorText;
} }
.icon-nd-shutdown:before {
.icon(@off);
color: @errorText;
}
.icon-nd-restart:before {
.icon(@repeat);
}

View File

@ -218,4 +218,27 @@ body {
width: 100%; width: 100%;
height: 55px; height: 55px;
opacity: 0; opacity: 0;
}
.lifecycle-controls {
font-size: 20px;
i {
cursor: pointer;
}
.drone-button {
height: .8em;
margin-left: -8px;
&:hover {
.icon-stack-base:before {
.icon(@sign-blank)
}
.icon-nd-restart:before {
color: white;
}
}
}
} }

View File

@ -5,12 +5,14 @@ define(
'marionette', 'marionette',
'System/Info/SystemInfoLayout', 'System/Info/SystemInfoLayout',
'System/Logs/LogsLayout', 'System/Logs/LogsLayout',
'System/Update/UpdateLayout' 'System/Update/UpdateLayout',
'Commands/CommandController'
], function (Backbone, ], function (Backbone,
Marionette, Marionette,
SystemInfoLayout, SystemInfoLayout,
LogsLayout, LogsLayout,
UpdateLayout) { UpdateLayout,
CommandController) {
return Marionette.Layout.extend({ return Marionette.Layout.extend({
template: 'System/SystemLayoutTemplate', template: 'System/SystemLayoutTemplate',
@ -27,9 +29,11 @@ define(
}, },
events: { events: {
'click .x-info-tab' : '_showInfo', 'click .x-info-tab' : '_showInfo',
'click .x-logs-tab' : '_showLogs', 'click .x-logs-tab' : '_showLogs',
'click .x-updates-tab': '_showUpdates' 'click .x-updates-tab': '_showUpdates',
'click .x-shutdown' : '_shutdown',
'click .x-restart' : '_restart'
}, },
initialize: function (options) { initialize: function (options) {
@ -83,6 +87,18 @@ define(
this.updates.show(new UpdateLayout()); this.updates.show(new UpdateLayout());
this.ui.updatesTab.tab('show'); this.ui.updatesTab.tab('show');
this._navigate('system/updates'); this._navigate('system/updates');
},
_shutdown: function () {
CommandController.Execute('shutdown', {
name : 'shutdown'
});
},
_restart: function () {
CommandController.Execute('restart', {
name : 'restart'
});
} }
}); });
}); });

View File

@ -2,6 +2,19 @@
<li><a href="#info" class="x-info-tab no-router">Info</a></li> <li><a href="#info" class="x-info-tab no-router">Info</a></li>
<li><a href="#logs" class="x-logs-tab no-router">Logs</a></li> <li><a href="#logs" class="x-logs-tab no-router">Logs</a></li>
<li><a href="#updates" class="x-updates-tab no-router">Updates</a></li> <li><a href="#updates" class="x-updates-tab no-router">Updates</a></li>
<li class="lifecycle-controls pull-right">
<span class="icon-stack drone-button x-shutdown">
<i class="icon-check-empty icon-stack-base"></i>
<i class="icon-nd-shutdown"></i>
</span>
{{#if_windows}}
<span class="icon-stack drone-button x-restart">
<i class="icon-check-empty icon-stack-base"></i>
<i class="icon-nd-restart"></i>
</span>
{{/if_windows}}
</li>
</ul> </ul>
<div class="tab-content"> <div class="tab-content">