From abb0df9b6d8f3d5baca2b69300ba20b6fc6d62ea Mon Sep 17 00:00:00 2001 From: Dave Reed Date: Mon, 7 Mar 2011 14:20:06 -0800 Subject: [PATCH] Added an AdminMenuPart to Navigation which lets you stick a content item onto the admin menu (e.g. a blog). --HG-- branch : dev --- .../Navigation/Drivers/AdminMenuPartDriver.cs | 50 +++++++++++++++++++ .../Handlers/AdminMenuPartHandler.cs | 19 +++++++ src/Orchard.Web/Core/Navigation/Migrations.cs | 14 ++++++ .../Core/Navigation/Models/AdminMenuPart.cs | 23 +++++++++ .../Navigation/Models/AdminMenuPartRecord.cs | 13 +++++ src/Orchard.Web/Core/Navigation/Module.txt | 2 +- .../Core/Navigation/Placement.info | 3 +- .../Services/AdminMenuNavigationProvider.cs | 41 +++++++++++++++ .../Parts.Navigation.AdminMenu.Edit.cshtml | 16 ++++++ src/Orchard.Web/Core/Orchard.Core.csproj | 8 +++ .../Modules/Orchard.Lists/Migrations.cs | 8 ++- src/Orchard/Utility/Position.cs | 2 +- 12 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 src/Orchard.Web/Core/Navigation/Drivers/AdminMenuPartDriver.cs create mode 100644 src/Orchard.Web/Core/Navigation/Handlers/AdminMenuPartHandler.cs create mode 100644 src/Orchard.Web/Core/Navigation/Models/AdminMenuPart.cs create mode 100644 src/Orchard.Web/Core/Navigation/Models/AdminMenuPartRecord.cs create mode 100644 src/Orchard.Web/Core/Navigation/Services/AdminMenuNavigationProvider.cs create mode 100644 src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml diff --git a/src/Orchard.Web/Core/Navigation/Drivers/AdminMenuPartDriver.cs b/src/Orchard.Web/Core/Navigation/Drivers/AdminMenuPartDriver.cs new file mode 100644 index 000000000..94a75247c --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Drivers/AdminMenuPartDriver.cs @@ -0,0 +1,50 @@ +using JetBrains.Annotations; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Drivers; +using Orchard.Core.Navigation.Models; +using Orchard.Localization; +using Orchard.Security; +using Orchard.UI.Navigation; +using Orchard.Utility; + +namespace Orchard.Core.Navigation.Drivers { + [UsedImplicitly] + public class AdminMenuPartDriver : ContentPartDriver { + private readonly IAuthorizationService _authorizationService; + private readonly INavigationManager _navigationManager; + private readonly IOrchardServices _orchardServices; + + public AdminMenuPartDriver(IAuthorizationService authorizationService, INavigationManager navigationManager, IOrchardServices orchardServices) { + _authorizationService = authorizationService; + _navigationManager = navigationManager; + _orchardServices = orchardServices; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + protected override DriverResult Editor(AdminMenuPart part, dynamic shapeHelper) { + // todo: we need a 'ManageAdminMenu' too? + if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part)) + return null; + + return ContentShape("Parts_Navigation_AdminMenu_Edit", + () => shapeHelper.EditorTemplate(TemplateName: "Parts.Navigation.AdminMenu.Edit", Model: part, Prefix: Prefix)); + } + + protected override DriverResult Editor(AdminMenuPart part, IUpdateModel updater, dynamic shapeHelper) { + if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part)) + return null; + + updater.TryUpdateModel(part, Prefix, null, null); + + if (part.OnAdminMenu && string.IsNullOrEmpty(part.AdminMenuText)) + updater.AddModelError("AdminMenuText", T("The AdminMenuText field is required")); + + if (string.IsNullOrEmpty(part.AdminMenuPosition)) + part.AdminMenuPosition = Position.GetNext(_navigationManager.BuildMenu("admin")); + + return Editor(part, shapeHelper); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Handlers/AdminMenuPartHandler.cs b/src/Orchard.Web/Core/Navigation/Handlers/AdminMenuPartHandler.cs new file mode 100644 index 000000000..3d7296da7 --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Handlers/AdminMenuPartHandler.cs @@ -0,0 +1,19 @@ +using System; +using JetBrains.Annotations; +using Orchard.ContentManagement.Handlers; +using Orchard.Core.Navigation.Models; +using Orchard.Data; + +namespace Orchard.Core.Navigation.Handlers { + [UsedImplicitly] + public class AdminMenuPartHandler : ContentHandler { + public AdminMenuPartHandler(IRepository menuPartRepository) { + Filters.Add(StorageFilter.For(menuPartRepository)); + + OnInitializing((ctx, x) => { + x.OnAdminMenu = false; + x.AdminMenuText = String.Empty; + }); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Migrations.cs b/src/Orchard.Web/Core/Navigation/Migrations.cs index 16eaee1e3..a2f7ce861 100644 --- a/src/Orchard.Web/Core/Navigation/Migrations.cs +++ b/src/Orchard.Web/Core/Navigation/Migrations.cs @@ -28,5 +28,19 @@ namespace Orchard.Core.Navigation { return 1; } + public int UpdateFrom1() { + SchemaBuilder.CreateTable("AdminMenuPartRecord", + table => table + .ContentPartRecord() + .Column("AdminMenuText") + .Column("AdminMenuPosition") + .Column("OnAdminMenu") + ); + ContentDefinitionManager.AlterPartDefinition("AdminMenuPart", builder => builder.Attachable()); + + ContentDefinitionManager.AlterTypeDefinition("Blog", cfg => cfg.WithPart("AdminMenuPart")); + return 2; + } + } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Models/AdminMenuPart.cs b/src/Orchard.Web/Core/Navigation/Models/AdminMenuPart.cs new file mode 100644 index 000000000..1c7bd2061 --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Models/AdminMenuPart.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using Orchard.ContentManagement; + +namespace Orchard.Core.Navigation.Models { + public class AdminMenuPart : ContentPart { + + public bool OnAdminMenu { + get { return Record.OnAdminMenu; } + set { Record.OnAdminMenu = value; } + } + + [StringLength(AdminMenuPartRecord.DefaultMenuTextLength)] + public string AdminMenuText { + get { return Record.AdminMenuText; } + set { Record.AdminMenuText = value; } + } + + public string AdminMenuPosition { + get { return Record.AdminMenuPosition; } + set { Record.AdminMenuPosition = value; } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Models/AdminMenuPartRecord.cs b/src/Orchard.Web/Core/Navigation/Models/AdminMenuPartRecord.cs new file mode 100644 index 000000000..69dec157b --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Models/AdminMenuPartRecord.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; +using Orchard.ContentManagement.Records; + +namespace Orchard.Core.Navigation.Models { + public class AdminMenuPartRecord : ContentPartRecord { + public const ushort DefaultMenuTextLength = 255; + + [StringLength(DefaultMenuTextLength)] + public virtual string AdminMenuText { get; set; } + public virtual string AdminMenuPosition { get; set; } + public virtual bool OnAdminMenu { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Module.txt b/src/Orchard.Web/Core/Navigation/Module.txt index fbf500af1..b6ee15e3a 100644 --- a/src/Orchard.Web/Core/Navigation/Module.txt +++ b/src/Orchard.Web/Core/Navigation/Module.txt @@ -4,7 +4,7 @@ Author: The Orchard Team Website: http://orchardproject.net Version: 1.0.20 OrchardVersion: 1.0.20 -Description: The navigation module creates and manages a simple navigation menu for the front-end of the application. +Description: The navigation module creates and manages a simple navigation menu for the front-end of the application and allows you to add content items to the admin menu. Features: Navigation: Description: Menu management. diff --git a/src/Orchard.Web/Core/Navigation/Placement.info b/src/Orchard.Web/Core/Navigation/Placement.info index 5b48f3af6..a7d1cabc2 100644 --- a/src/Orchard.Web/Core/Navigation/Placement.info +++ b/src/Orchard.Web/Core/Navigation/Placement.info @@ -1,3 +1,4 @@  - + + \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Services/AdminMenuNavigationProvider.cs b/src/Orchard.Web/Core/Navigation/Services/AdminMenuNavigationProvider.cs new file mode 100644 index 000000000..1c78367fc --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Services/AdminMenuNavigationProvider.cs @@ -0,0 +1,41 @@ +using System.Web; +using JetBrains.Annotations; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.Core.Navigation.Models; +using Orchard.Localization; +using Orchard.UI.Navigation; + +namespace Orchard.Core.Navigation.Services { + [UsedImplicitly] + public class AdminMenuNavigationProvider : INavigationProvider { + private readonly IContentManager _contentManager; + private readonly IContentDefinitionManager _contentDefinitionManager; + + public AdminMenuNavigationProvider(IContentManager contentManager, IContentDefinitionManager contentDefinitionManager) { + _contentManager = contentManager; + _contentDefinitionManager = contentDefinitionManager; + } + + public string MenuName { get { return "admin"; } } + + public void GetNavigation(NavigationBuilder builder) { + var partDefinition = _contentDefinitionManager.GetPartDefinition("AdminMenuPart"); + // if the part doesn't even exist, it hasn't been migrated yet... trying to query for AdminMenuPart items would cause an error. + if (partDefinition != null) { + var menuParts = _contentManager.Query().Where(x => x.OnAdminMenu).List(); + foreach (var menuPart in menuParts) { + if (menuPart != null) { + var part = menuPart; + + builder.Add(new LocalizedString(HttpUtility.HtmlEncode(part.AdminMenuText)), + part.AdminMenuPosition, + item => item.Action(_contentManager.GetItemMetadata(part.ContentItem).AdminRouteValues)); + // todo: somehow determine if they will ultimately have rights to the destination and hide if not. possibly would need to add a Permission to metadata. + // todo: give an iconset somehow (e.g. based on convention, module/content/.adminmenu.png). + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml b/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml new file mode 100644 index 000000000..e976404ae --- /dev/null +++ b/src/Orchard.Web/Core/Navigation/Views/EditorTemplates/Parts.Navigation.AdminMenu.Edit.cshtml @@ -0,0 +1,16 @@ +@model AdminMenuPart +@using Orchard.Core.Navigation.Models; +@{ + Script.Require("ShapesBase"); +} +
+ @Html.EditorFor(m => m.OnAdminMenu) + +
+ + @Html.TextBoxFor(m => m.AdminMenuText, new { @class = "large text" }) + + + @Html.TextBoxFor(m => m.AdminMenuPosition) +
+
diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 2c306eb18..2109b0297 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -105,6 +105,11 @@ + + + + + @@ -409,6 +414,9 @@ + + +