Implemented an Admin banner notification system

- INotificationProvider class to enlist steady messages in the Admin pages
- DataMigrationNotificationProvider displays a message when upgrades are needed

--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-07-09 12:14:26 -07:00
parent caef8cd1e8
commit d978346283
9 changed files with 138 additions and 3 deletions

View File

@@ -289,7 +289,9 @@
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Body.Manage.ascx" />
<Content Include="Dashboard\Views\Web.config" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="Notification\" />
</ItemGroup>
<ItemGroup>
<None Include="App_Data\Localization\en-US\orchard.core.po" />
<None Include="App_Data\Localization\fr-FR\orchard.core.po" />

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Orchard.Caching;
using Orchard.Data.Migration.Interpreters;
using Orchard.Data.Migration.Records;
using Orchard.Data.Migration.Schema;
@@ -19,17 +20,20 @@ namespace Orchard.Data.Migration {
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
private readonly IExtensionManager _extensionManager;
private readonly IDataMigrationInterpreter _interpreter;
private readonly ISignals _signals;
public DataMigrationManager(
IEnumerable<IDataMigration> dataMigrations,
IRepository<DataMigrationRecord> dataMigrationRepository,
IExtensionManager extensionManager,
IDataMigrationInterpreter interpreter
IDataMigrationInterpreter interpreter,
ISignals signals
) {
_dataMigrations = dataMigrations;
_dataMigrationRepository = dataMigrationRepository;
_extensionManager = extensionManager;
_interpreter = interpreter;
_signals = signals;
Logger = NullLogger.Instance;
}
@@ -78,7 +82,9 @@ namespace Orchard.Data.Migration {
}
public void Update(string feature){
// invalidate the notifications cache
_signals.Trigger(DataMigrationNotificationProvider.SignalKey);
Logger.Information("Updating {0}", feature);
// proceed with dependent features first, whatever the module it's in
@@ -146,6 +152,8 @@ namespace Orchard.Data.Migration {
}
public void Uninstall(string feature) {
// invalidate the notifications cache
_signals.Trigger(DataMigrationNotificationProvider.SignalKey);
var migrations = GetDataMigrations(feature);

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Caching;
using Orchard.Localization;
using Orchard.UI.Admin.Notification;
using Orchard.UI.Notify;
namespace Orchard.Data.Migration {
public class DataMigrationNotificationProvider: INotificationProvider {
private readonly IDataMigrationManager _dataMigrationManager;
private readonly ICacheManager _cacheManager;
private readonly ISignals _signals;
public const string CacheKey = "DataMigrationNotifications";
public const string SignalKey = "DataMigrationNotificationsChanged";
public DataMigrationNotificationProvider(IDataMigrationManager dataMigrationManager, ICacheManager cacheManager, ISignals signals) {
_dataMigrationManager = dataMigrationManager;
_cacheManager = cacheManager;
_signals = signals;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public IEnumerable<NotifyEntry> GetNotifications() {
var features = _cacheManager.Get(CacheKey, ctx => {
ctx.Monitor(_signals.When(SignalKey));
return _dataMigrationManager.GetFeaturesThatNeedUpdate();
});
if(features.Any()) {
yield return new NotifyEntry { Message = T("Some features need to be upgraded: {0}", String.Join(", ", features)), Type = NotifyType.Warning};
}
}
}
}

View File

@@ -407,6 +407,11 @@
<Compile Include="Environment\Extensions\Compilers\ProjectFileDescriptor.cs" />
<Compile Include="Environment\Extensions\Compilers\IProjectFileParser.cs" />
<Compile Include="Localization\Commands\CultureCommands.cs" />
<Compile Include="UI\Admin\Notification\NotificationFilter.cs" />
<Compile Include="Data\Migration\DataMigrationNotificationProvider.cs" />
<Compile Include="UI\Admin\Notification\INotificationManager.cs" />
<Compile Include="UI\Admin\Notification\INotificationProvider.cs" />
<Compile Include="UI\Admin\Notification\NotificationManager.cs" />
<Compile Include="Utility\DependencyOrderingUtility.cs" />
<Compile Include="Environment\IOrchardHostContainer.cs" />
<Compile Include="Environment\IShim.cs" />

View File

@@ -5,7 +5,9 @@ using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Localization;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard.UI.Admin {
public class AdminFilter : FilterProvider, IAuthorizationFilter {
@@ -65,5 +67,6 @@ namespace Orchard.UI.Admin {
.Concat(descriptor.ControllerDescriptor.GetCustomAttributes(typeof(AdminAttribute), true))
.OfType<AdminAttribute>();
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.UI.Notify;
namespace Orchard.UI.Admin.Notification {
public interface INotificationManager : IDependency {
/// <summary>
/// Returns all notifications to display per zone
/// </summary>
IEnumerable<NotifyEntry> GetNotifications();
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.UI.Notify;
namespace Orchard.UI.Admin.Notification {
public interface INotificationProvider : IDependency {
/// <summary>
/// Returns all notifications to display per zone
/// </summary>
IEnumerable<NotifyEntry> GetNotifications();
}
}

View File

@@ -0,0 +1,40 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels;
namespace Orchard.UI.Admin.Notification {
public class AdminNotificationFilter : FilterProvider, IResultFilter {
private readonly INotificationManager _notificationManager;
public AdminNotificationFilter(INotificationManager notificationManager) {
_notificationManager = notificationManager;
}
public void OnResultExecuting(ResultExecutingContext filterContext) {
if ( !AdminFilter.IsApplied(filterContext.RequestContext) ) {
return;
}
var viewResult = filterContext.Result as ViewResultBase;
// if it's not a view result, a redirect for example
if ( viewResult == null )
return;
var baseViewModel = BaseViewModel.From(viewResult);
// if it's not a view model that holds messages, don't touch temp data either
if ( baseViewModel == null )
return;
var messageEntries = _notificationManager.GetNotifications().ToList();
baseViewModel.Messages = baseViewModel.Messages == null ? messageEntries : baseViewModel.Messages.Union(messageEntries).ToList();
baseViewModel.Zones.AddRenderPartial("content:before", "Messages", baseViewModel.Messages);
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.UI.Notify;
namespace Orchard.UI.Admin.Notification {
public class NotificationManager : INotificationManager {
private readonly IEnumerable<INotificationProvider> _notificationProviders;
public NotificationManager(IEnumerable<INotificationProvider> notificationProviders) {
_notificationProviders = notificationProviders;
}
public IEnumerable<NotifyEntry> GetNotifications() {
return _notificationProviders
.SelectMany(n => n.GetNotifications());
}
}
}