From d9783462832b914264d1951ba013d42599d92049 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Fri, 9 Jul 2010 12:14:26 -0700 Subject: [PATCH] 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 --- src/Orchard.Web/Core/Orchard.Core.csproj | 4 +- .../Data/Migration/DataMigrationManager.cs | 12 +++++- .../DataMigrationNotificationProvider.cs | 37 +++++++++++++++++ src/Orchard/Orchard.Framework.csproj | 5 +++ src/Orchard/UI/Admin/AdminFilter.cs | 3 ++ .../Notification/INotificationManager.cs | 11 +++++ .../Notification/INotificationProvider.cs | 11 +++++ .../Admin/Notification/NotificationFilter.cs | 40 +++++++++++++++++++ .../Admin/Notification/NotificationManager.cs | 18 +++++++++ 9 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/Orchard/Data/Migration/DataMigrationNotificationProvider.cs create mode 100644 src/Orchard/UI/Admin/Notification/INotificationManager.cs create mode 100644 src/Orchard/UI/Admin/Notification/INotificationProvider.cs create mode 100644 src/Orchard/UI/Admin/Notification/NotificationFilter.cs create mode 100644 src/Orchard/UI/Admin/Notification/NotificationManager.cs diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index b798985a9..e8bf3efd9 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -289,7 +289,9 @@ - + + + diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 0cff7912a..637a9aaef 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -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 _dataMigrationRepository; private readonly IExtensionManager _extensionManager; private readonly IDataMigrationInterpreter _interpreter; + private readonly ISignals _signals; public DataMigrationManager( IEnumerable dataMigrations, IRepository 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); diff --git a/src/Orchard/Data/Migration/DataMigrationNotificationProvider.cs b/src/Orchard/Data/Migration/DataMigrationNotificationProvider.cs new file mode 100644 index 000000000..a5e854a6b --- /dev/null +++ b/src/Orchard/Data/Migration/DataMigrationNotificationProvider.cs @@ -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 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}; + } + } + } +} diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index b94b67613..626c8a181 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -407,6 +407,11 @@ + + + + + diff --git a/src/Orchard/UI/Admin/AdminFilter.cs b/src/Orchard/UI/Admin/AdminFilter.cs index 36b47c88d..fb4c82dbc 100644 --- a/src/Orchard/UI/Admin/AdminFilter.cs +++ b/src/Orchard/UI/Admin/AdminFilter.cs @@ -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(); } + } } \ No newline at end of file diff --git a/src/Orchard/UI/Admin/Notification/INotificationManager.cs b/src/Orchard/UI/Admin/Notification/INotificationManager.cs new file mode 100644 index 000000000..053adbb5a --- /dev/null +++ b/src/Orchard/UI/Admin/Notification/INotificationManager.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Orchard.UI.Notify; + +namespace Orchard.UI.Admin.Notification { + public interface INotificationManager : IDependency { + /// + /// Returns all notifications to display per zone + /// + IEnumerable GetNotifications(); + } +} diff --git a/src/Orchard/UI/Admin/Notification/INotificationProvider.cs b/src/Orchard/UI/Admin/Notification/INotificationProvider.cs new file mode 100644 index 000000000..ee0c0429a --- /dev/null +++ b/src/Orchard/UI/Admin/Notification/INotificationProvider.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Orchard.UI.Notify; + +namespace Orchard.UI.Admin.Notification { + public interface INotificationProvider : IDependency { + /// + /// Returns all notifications to display per zone + /// + IEnumerable GetNotifications(); + } +} diff --git a/src/Orchard/UI/Admin/Notification/NotificationFilter.cs b/src/Orchard/UI/Admin/Notification/NotificationFilter.cs new file mode 100644 index 000000000..0ee86cd74 --- /dev/null +++ b/src/Orchard/UI/Admin/Notification/NotificationFilter.cs @@ -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) { + + } + } +} diff --git a/src/Orchard/UI/Admin/Notification/NotificationManager.cs b/src/Orchard/UI/Admin/Notification/NotificationManager.cs new file mode 100644 index 000000000..bb15ac9c8 --- /dev/null +++ b/src/Orchard/UI/Admin/Notification/NotificationManager.cs @@ -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 _notificationProviders; + + public NotificationManager(IEnumerable notificationProviders) { + _notificationProviders = notificationProviders; + } + + public IEnumerable GetNotifications() { + return _notificationProviders + .SelectMany(n => n.GetNotifications()); + } + } +}