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="Common\Views\DisplayTemplates\Parts\Common.Body.Manage.ascx" />
<Content Include="Dashboard\Views\Web.config" /> <Content Include="Dashboard\Views\Web.config" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<Folder Include="Notification\" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App_Data\Localization\en-US\orchard.core.po" /> <None Include="App_Data\Localization\en-US\orchard.core.po" />
<None Include="App_Data\Localization\fr-FR\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.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Orchard.Caching;
using Orchard.Data.Migration.Interpreters; using Orchard.Data.Migration.Interpreters;
using Orchard.Data.Migration.Records; using Orchard.Data.Migration.Records;
using Orchard.Data.Migration.Schema; using Orchard.Data.Migration.Schema;
@@ -19,17 +20,20 @@ namespace Orchard.Data.Migration {
private readonly IRepository<DataMigrationRecord> _dataMigrationRepository; private readonly IRepository<DataMigrationRecord> _dataMigrationRepository;
private readonly IExtensionManager _extensionManager; private readonly IExtensionManager _extensionManager;
private readonly IDataMigrationInterpreter _interpreter; private readonly IDataMigrationInterpreter _interpreter;
private readonly ISignals _signals;
public DataMigrationManager( public DataMigrationManager(
IEnumerable<IDataMigration> dataMigrations, IEnumerable<IDataMigration> dataMigrations,
IRepository<DataMigrationRecord> dataMigrationRepository, IRepository<DataMigrationRecord> dataMigrationRepository,
IExtensionManager extensionManager, IExtensionManager extensionManager,
IDataMigrationInterpreter interpreter IDataMigrationInterpreter interpreter,
ISignals signals
) { ) {
_dataMigrations = dataMigrations; _dataMigrations = dataMigrations;
_dataMigrationRepository = dataMigrationRepository; _dataMigrationRepository = dataMigrationRepository;
_extensionManager = extensionManager; _extensionManager = extensionManager;
_interpreter = interpreter; _interpreter = interpreter;
_signals = signals;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
@@ -78,6 +82,8 @@ namespace Orchard.Data.Migration {
} }
public void Update(string feature){ public void Update(string feature){
// invalidate the notifications cache
_signals.Trigger(DataMigrationNotificationProvider.SignalKey);
Logger.Information("Updating {0}", feature); Logger.Information("Updating {0}", feature);
@@ -146,6 +152,8 @@ namespace Orchard.Data.Migration {
} }
public void Uninstall(string feature) { public void Uninstall(string feature) {
// invalidate the notifications cache
_signals.Trigger(DataMigrationNotificationProvider.SignalKey);
var migrations = GetDataMigrations(feature); 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\ProjectFileDescriptor.cs" />
<Compile Include="Environment\Extensions\Compilers\IProjectFileParser.cs" /> <Compile Include="Environment\Extensions\Compilers\IProjectFileParser.cs" />
<Compile Include="Localization\Commands\CultureCommands.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="Utility\DependencyOrderingUtility.cs" />
<Compile Include="Environment\IOrchardHostContainer.cs" /> <Compile Include="Environment\IOrchardHostContainer.cs" />
<Compile Include="Environment\IShim.cs" /> <Compile Include="Environment\IShim.cs" />

View File

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