Updated MenuItemCollection with MenuItemList for full featured List access to the items. Added the MenuRendering event to TreeController, updated the tree controller events to be TypedEventHandler's though developers will need to cast the TreeController to the type they are expecting - still better than 'object'.

This commit is contained in:
Shannon
2013-10-03 15:05:48 +10:00
parent ed8f22c371
commit 936be3934b
14 changed files with 303 additions and 238 deletions

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
menu.AddMenuItem(new MenuItem("create", "Create"));
menu.Add(new MenuItem("create", "Create"));
return menu;
}
}

View File

@@ -107,20 +107,20 @@ namespace Umbraco.Web.Trees
.Select(x => new MenuItem(x));
//these two are the standard items
menu.AddMenuItem<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(null, "content", "content");
menu.Items.Add<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(null, "content", "content");
//filter the standard items
FilterUserAllowedMenuItems(menu, nodeActions);
if (menu.MenuItems.Any())
if (menu.Items.Any())
{
menu.MenuItems.Last().SeperatorBefore = true;
menu.Items.Last().SeperatorBefore = true;
}
// add default actions for *all* users
menu.AddMenuItem<ActionRePublish>(ui.Text("actions", ActionRePublish.Instance.Alias)).ConvertLegacyMenuItem(null, "content", "content");
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionRePublish>(ui.Text("actions", ActionRePublish.Instance.Alias)).ConvertLegacyMenuItem(null, "content", "content");
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
@@ -162,26 +162,26 @@ namespace Umbraco.Web.Trees
protected MenuItemCollection GetAllNodeMenuItems(IUmbracoEntity item)
{
var menu = new MenuItemCollection();
menu.AddMenuItem<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.Items.Add<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
//need to ensure some of these are converted to the legacy system - until we upgrade them all to be angularized.
menu.AddMenuItem<ActionMove>(ui.Text("actions", ActionMove.Instance.Alias), true);
menu.AddMenuItem<ActionCopy>(ui.Text("actions", ActionCopy.Instance.Alias));
menu.Items.Add<ActionMove>(ui.Text("actions", ActionMove.Instance.Alias), true);
menu.Items.Add<ActionCopy>(ui.Text("actions", ActionCopy.Instance.Alias));
menu.AddMenuItem<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionRollback>(ui.Text("actions", ActionRollback.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionPublish>(ui.Text("actions", ActionPublish.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionToPublish>(ui.Text("actions", ActionToPublish.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionAssignDomain>(ui.Text("actions", ActionAssignDomain.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionRights>(ui.Text("actions", ActionRights.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionProtect>(ui.Text("actions", ActionProtect.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionUnPublish>(ui.Text("actions", ActionUnPublish.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionNotify>(ui.Text("actions", ActionNotify.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<ActionSendToTranslate>(ui.Text("actions", ActionSendToTranslate.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionRollback>(ui.Text("actions", ActionRollback.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionPublish>(ui.Text("actions", ActionPublish.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionToPublish>(ui.Text("actions", ActionToPublish.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionAssignDomain>(ui.Text("actions", ActionAssignDomain.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionRights>(ui.Text("actions", ActionRights.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionProtect>(ui.Text("actions", ActionProtect.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionUnPublish>(ui.Text("actions", ActionUnPublish.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionNotify>(ui.Text("actions", ActionNotify.Instance.Alias), true).ConvertLegacyMenuItem(item, "content", "content");
menu.Items.Add<ActionSendToTranslate>(ui.Text("actions", ActionSendToTranslate.Instance.Alias)).ConvertLegacyMenuItem(item, "content", "content");
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}

View File

@@ -96,8 +96,8 @@ namespace Umbraco.Web.Trees
if (RecycleBinId.ToInvariantString() == id)
{
var menu = new MenuItemCollection();
menu.AddMenuItem<ActionEmptyTranscan>(ui.Text("actions", ActionEmptyTranscan.Instance.Alias));
menu.AddMenuItem<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionEmptyTranscan>(ui.Text("actions", ActionEmptyTranscan.Instance.Alias));
menu.Items.Add<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
return PerformGetMenuForNode(id, queryStrings);
@@ -113,7 +113,7 @@ namespace Umbraco.Web.Trees
{
var userAllowedActions = userAllowedMenuItems.Where(x => x.Action != null).Select(x => x.Action).ToArray();
var notAllowed = menuWithAllItems.MenuItems.Where(
var notAllowed = menuWithAllItems.Items.Where(
a => (a.Action != null
&& a.Action.CanBePermissionAssigned
&& (a.Action.CanBePermissionAssigned == false || userAllowedActions.Contains(a.Action) == false)))
@@ -122,7 +122,7 @@ namespace Umbraco.Web.Trees
//remove the ones that aren't allowed.
foreach (var m in notAllowed)
{
menuWithAllItems.RemoveMenuItem(m);
menuWithAllItems.Items.Remove(m);
}
}

View File

@@ -47,13 +47,13 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
menu.AddMenuItem<CreateChildEntity, ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<CreateChildEntity, ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
//only have delete for each node
menu.AddMenuItem<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
return menu;
}
}

View File

@@ -75,7 +75,7 @@ namespace Umbraco.Web.Trees
throw new ApplicationException(msg);
}
foreach (var menuItem in attempt.Result.MenuItems)
foreach (var menuItem in attempt.Result.Items)
{
menuItem.Name = global::umbraco.ui.Text("actions", menuItem.Alias);
}
@@ -90,7 +90,7 @@ namespace Umbraco.Web.Trees
LogHelper.Error<LegacyTreeController>(msg, attempt.Exception);
throw new ApplicationException(msg);
}
foreach (var menuItem in attempt.Result.MenuItems)
foreach (var menuItem in attempt.Result.Items)
{
menuItem.Name = global::umbraco.ui.Text("actions", menuItem.Alias);
}

View File

@@ -143,11 +143,11 @@ namespace Umbraco.Web.Trees
if (t is ContextMenuSeperator && numAdded > 0)
{
//store the index for which the seperator should be placed
seperators.Add(collection.MenuItems.Count());
seperators.Add(collection.Items.Count());
}
else
{
var menuItem = collection.AddMenuItem(t, ui.Text("actions", t.Alias));
var menuItem = collection.Items.Add(t, ui.Text("actions", t.Alias));
var currentAction = t;
@@ -164,12 +164,12 @@ namespace Umbraco.Web.Trees
numAdded++;
}
}
var length = collection.MenuItems.Count();
var length = collection.Items.Count();
foreach (var s in seperators)
{
if (length >= s)
{
collection.MenuItems.ElementAt(s).SeperatorBefore = true;
collection.Items.ElementAt(s).SeperatorBefore = true;
}
}

View File

@@ -77,9 +77,9 @@ namespace Umbraco.Web.Trees
}
// root actions
menu.AddMenuItem<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(null, "media", "media");
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias), true).ConvertLegacyMenuItem(null, "media", "media");
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
@@ -94,11 +94,11 @@ namespace Umbraco.Web.Trees
throw new HttpResponseException(HttpStatusCode.NotFound);
}
//return a normal node menu:
menu.AddMenuItem<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<ActionMove>(ui.Text("actions", ActionMove.Instance.Alias));
menu.AddMenuItem<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.AddMenuItem<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias)).ConvertLegacyMenuItem(null, "media", "media");
menu.AddMenuItem<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<ActionMove>(ui.Text("actions", ActionMove.Instance.Alias));
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.Items.Add<ActionSort>(ui.Text("actions", ActionSort.Instance.Alias)).ConvertLegacyMenuItem(null, "media", "media");
menu.Items.Add<ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}

View File

@@ -80,13 +80,13 @@ namespace Umbraco.Web.Trees
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
// root actions
menu.AddMenuItem<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
menu.AddMenuItem<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.AddMenuItem<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
}

View File

@@ -1,28 +1,24 @@
using System;
using System.Collections;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core;
using umbraco.BusinessLogic.Actions;
using umbraco.interfaces;
namespace Umbraco.Web.Trees.Menu
{
/// <summary>
/// A menu item collection for a given tree node
/// </summary>
[DataContract(Name = "menuItems", Namespace = "")]
public class MenuItemCollection
public class MenuItemCollection
{
//private readonly string _packageFolderName;
private readonly List<MenuItem> _menuItems;
private readonly MenuItemList _menuItems = new MenuItemList();
public MenuItemCollection()
{
_menuItems = new List<MenuItem>();
{
}
public MenuItemCollection(IEnumerable<MenuItem> items)
{
_menuItems = new List<MenuItem>(items);
_menuItems = new MenuItemList(items);
}
/// <summary>
@@ -34,184 +30,16 @@ namespace Umbraco.Web.Trees.Menu
/// <summary>
/// The list of menu items
/// </summary>
/// <remarks>
/// We require this so the json serialization works correctly
/// </remarks>
[DataMember(Name = "menuItems")]
public IEnumerable<MenuItem> MenuItems
public MenuItemList Items
{
get { return _menuItems; }
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <param name="action"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
internal MenuItem AddMenuItem(IAction action, string name)
{
var item = new MenuItem(action);
DetectLegacyActionMenu(action.GetType(), item);
_menuItems.Add(item);
return item;
}
/// <summary>
/// Removes a menu item
/// </summary>
/// <param name="item"></param>
public void RemoveMenuItem(MenuItem item)
{
_menuItems.Remove(item);
}
/// <summary>
/// Adds a menu item
/// </summary>
public void AddMenuItem(MenuItem item)
{
_menuItems.Add(item);
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <typeparam name="TMenuItem"></typeparam>
/// <typeparam name="TAction"></typeparam>
/// <param name="hasSeparator"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
/// <returns></returns>
public TMenuItem AddMenuItem<TMenuItem, TAction>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where TAction : IAction
where TMenuItem : MenuItem, new()
{
var item = CreateMenuItem<TAction>(name, hasSeparator, additionalData);
if (item == null) return null;
var customMenuItem = new TMenuItem
{
Name = item.Alias,
Alias = item.Alias,
SeperatorBefore = hasSeparator,
Icon = item.Icon,
Action = item.Action
};
_menuItems.Add(customMenuItem);
return customMenuItem;
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <typeparam name="T"></typeparam>
public MenuItem AddMenuItem<T>(string name)
where T : IAction
{
return AddMenuItem<T>(name, false, null);
}
/// <summary>
/// Adds a menu item with a key value pair which is merged to the AdditionalData bag
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="hasSeparator"></param>
public MenuItem AddMenuItem<T>(string name, string key, string value, bool hasSeparator = false)
where T : IAction
{
return AddMenuItem<T>(name, hasSeparator, new Dictionary<string, object> { { key, value } });
}
/// <summary>
/// Adds a menu item with a dictionary which is merged to the AdditionalData bag
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hasSeparator"></param>
/// /// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
public MenuItem AddMenuItem<T>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where T : IAction
{
var item = CreateMenuItem<T>(name, hasSeparator, additionalData);
if (item != null)
{
_menuItems.Add(item);
return item;
}
return null;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hasSeparator"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
/// <returns></returns>
internal MenuItem CreateMenuItem<T>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where T : IAction
{
var item = ActionsResolver.Current.GetAction<T>();
if (item != null)
{
var menuItem = new MenuItem(item, name)
{
SeperatorBefore = hasSeparator
};
if (additionalData != null)
{
foreach (var i in additionalData)
{
menuItem.AdditionalData[i.Key] = i.Value;
}
}
DetectLegacyActionMenu(typeof(T), menuItem);
//TODO: Once we implement 'real' menu items, not just IActions we can implement this since
// people may need to pass specific data to their menu items
////validate the data in the meta data bag
//item.ValidateRequiredData(AdditionalData);
return menuItem;
}
return null;
}
/// <summary>
/// Checks if the IAction type passed in is attributed with LegacyActionMenuItemAttribute and if so
/// ensures that the correct action metadata is added.
/// </summary>
/// <param name="actionType"></param>
/// <param name="menuItem"></param>
private void DetectLegacyActionMenu(Type actionType, MenuItem menuItem)
{
//This checks for legacy IActions that have the LegacyActionMenuItemAttribute which is a legacy hack
// to make old IAction actions work in v7 by mapping to the JS used by the new menu items
var attribute = actionType.GetCustomAttribute<LegacyActionMenuItemAttribute>(false);
if (attribute != null)
{
//add the current type to the metadata
if (attribute.MethodName.IsNullOrWhiteSpace())
{
//if no method name is supplied we will assume that the menu action is the type name of the current menu class
menuItem.AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name));
}
else
{
menuItem.AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName));
}
}
}
}
}

View File

@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using Umbraco.Core;
using umbraco.BusinessLogic.Actions;
using umbraco.interfaces;
namespace Umbraco.Web.Trees.Menu
{
/// <summary>
/// A custom menu list
/// </summary>
/// <remarks>
/// NOTE: We need a sub collection to the MenuItemCollection object due to how json serialization works.
/// </remarks>
public class MenuItemList : List<MenuItem>
{
public MenuItemList()
{
}
public MenuItemList(IEnumerable<MenuItem> items)
: base(items)
{
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <param name="action"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
internal MenuItem Add(IAction action, string name)
{
var item = new MenuItem(action);
DetectLegacyActionMenu(action.GetType(), item);
Add(item);
return item;
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <typeparam name="TMenuItem"></typeparam>
/// <typeparam name="TAction"></typeparam>
/// <param name="hasSeparator"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
/// <returns></returns>
public TMenuItem Add<TMenuItem, TAction>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where TAction : IAction
where TMenuItem : MenuItem, new()
{
var item = CreateMenuItem<TAction>(name, hasSeparator, additionalData);
if (item == null) return null;
var customMenuItem = new TMenuItem
{
Name = item.Alias,
Alias = item.Alias,
SeperatorBefore = hasSeparator,
Icon = item.Icon,
Action = item.Action
};
Add(customMenuItem);
return customMenuItem;
}
/// <summary>
/// Adds a menu item
/// </summary>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <typeparam name="T"></typeparam>
public MenuItem Add<T>(string name)
where T : IAction
{
return Add<T>(name, false, null);
}
/// <summary>
/// Adds a menu item with a key value pair which is merged to the AdditionalData bag
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="hasSeparator"></param>
public MenuItem Add<T>(string name, string key, string value, bool hasSeparator = false)
where T : IAction
{
return Add<T>(name, hasSeparator, new Dictionary<string, object> { { key, value } });
}
/// <summary>
/// Adds a menu item with a dictionary which is merged to the AdditionalData bag
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hasSeparator"></param>
/// /// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
public MenuItem Add<T>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where T : IAction
{
var item = CreateMenuItem<T>(name, hasSeparator, additionalData);
if (item != null)
{
Add(item);
return item;
}
return null;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="hasSeparator"></param>
/// <param name="name">The text to display for the menu item, will default to the IAction alias if not specified</param>
/// <param name="additionalData"></param>
/// <returns></returns>
internal MenuItem CreateMenuItem<T>(string name, bool hasSeparator = false, IDictionary<string, object> additionalData = null)
where T : IAction
{
var item = ActionsResolver.Current.GetAction<T>();
if (item != null)
{
var menuItem = new MenuItem(item, name)
{
SeperatorBefore = hasSeparator
};
if (additionalData != null)
{
foreach (var i in additionalData)
{
menuItem.AdditionalData[i.Key] = i.Value;
}
}
DetectLegacyActionMenu(typeof(T), menuItem);
//TODO: Once we implement 'real' menu items, not just IActions we can implement this since
// people may need to pass specific data to their menu items
////validate the data in the meta data bag
//item.ValidateRequiredData(AdditionalData);
return menuItem;
}
return null;
}
/// <summary>
/// Checks if the IAction type passed in is attributed with LegacyActionMenuItemAttribute and if so
/// ensures that the correct action metadata is added.
/// </summary>
/// <param name="actionType"></param>
/// <param name="menuItem"></param>
private void DetectLegacyActionMenu(Type actionType, MenuItem menuItem)
{
//This checks for legacy IActions that have the LegacyActionMenuItemAttribute which is a legacy hack
// to make old IAction actions work in v7 by mapping to the JS used by the new menu items
var attribute = actionType.GetCustomAttribute<LegacyActionMenuItemAttribute>(false);
if (attribute != null)
{
//add the current type to the metadata
if (attribute.MethodName.IsNullOrWhiteSpace())
{
//if no method name is supplied we will assume that the menu action is the type name of the current menu class
menuItem.AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name));
}
else
{
menuItem.AdditionalData.Add("jsAction", string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName));
}
}
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Net.Http.Formatting;
using Umbraco.Web.Trees.Menu;
namespace Umbraco.Web.Trees
{
public class MenuRenderingEventArgs : TreeRenderingEventArgs
{
/// <summary>
/// The tree node id that the menu is rendering for
/// </summary>
public string NodeId { get; private set; }
/// <summary>
/// The menu being rendered
/// </summary>
public MenuItemCollection Menu { get; private set; }
public MenuRenderingEventArgs(string nodeId, MenuItemCollection menu, FormDataCollection queryStrings)
: base(queryStrings)
{
NodeId = nodeId;
Menu = menu;
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using System.Net.Http.Formatting;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Web.Mvc;
using Umbraco.Web.Trees.Menu;
using Umbraco.Web.WebApi;
@@ -164,7 +165,10 @@ namespace Umbraco.Web.Trees
public MenuItemCollection GetMenu(string id, FormDataCollection queryStrings)
{
if (queryStrings == null) queryStrings = new FormDataCollection("");
return GetMenuForNode(id, queryStrings);
var menu = GetMenuForNode(id, queryStrings);
//raise the event
OnMenuRendering(this, new MenuRenderingEventArgs(id, menu, queryStrings));
return menu;
}
/// <summary>
@@ -304,7 +308,14 @@ namespace Umbraco.Web.Trees
#endregion
#region Events
public static event EventHandler<TreeNodesRenderingEventArgs> TreeNodesRendering;
/// <summary>
/// An event that allows developers to modify the tree node collection that is being rendered
/// </summary>
/// <remarks>
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
/// </remarks>
public static event TypedEventHandler<TreeController, TreeNodesRenderingEventArgs> TreeNodesRendering;
private static void OnTreeNodesRendering(TreeController instance, TreeNodesRenderingEventArgs e)
{
@@ -312,13 +323,31 @@ namespace Umbraco.Web.Trees
if (handler != null) handler(instance, e);
}
public static event EventHandler<TreeNodeRenderingEventArgs> RootNodeRendering;
/// <summary>
/// An event that allows developer to modify the root tree node that is being rendered
/// </summary>
public static event TypedEventHandler<TreeController, TreeNodeRenderingEventArgs> RootNodeRendering;
private static void OnRootNodeRendering(TreeController instance, TreeNodeRenderingEventArgs e)
{
var handler = RootNodeRendering;
if (handler != null) handler(instance, e);
}
}
/// <summary>
/// An event that allows developers to modify the meun that is being rendered
/// </summary>
/// <remarks>
/// Developers can add/remove/replace/insert/update/etc... any of the tree items in the collection.
/// </remarks>
public static event TypedEventHandler<TreeController, MenuRenderingEventArgs> MenuRendering;
private static void OnMenuRendering(TreeController instance, MenuRenderingEventArgs e)
{
var handler = MenuRendering;
if (handler != null) handler(instance, e);
}
#endregion
}

View File

@@ -6,7 +6,7 @@ namespace Umbraco.Web.Trees
{
public TreeNode Node { get; private set; }
public TreeNodeRenderingEventArgs(TreeNode node, FormDataCollection queryStrings)
public TreeNodeRenderingEventArgs(TreeNode node, FormDataCollection queryStrings)
: base(queryStrings)
{
Node = node;

View File

@@ -372,7 +372,9 @@
<Compile Include="Routing\UrlProviderExtensions.cs" />
<Compile Include="Trees\DataTypeTreeController.cs" />
<Compile Include="Trees\MemberTreeController.cs" />
<Compile Include="Trees\MenuRenderingEventArgs.cs" />
<Compile Include="Trees\Menu\CreateChildEntity.cs" />
<Compile Include="Trees\Menu\MenuItemList.cs" />
<Compile Include="UI\JavaScript\CssInitialization.cs" />
<Compile Include="umbraco.presentation\umbraco\create.aspx.cs">
<SubType>ASPXCodeBehind</SubType>