Refactors how the 'OpensDialog' gets assigned to menu items, fixes permission check on rollback

This commit is contained in:
Shannon
2018-10-30 00:34:43 +11:00
parent b8a65febf4
commit 77f4f0bbad
19 changed files with 89 additions and 80 deletions

View File

@@ -10,7 +10,9 @@ namespace Umbraco.Web.Actions
/// </summary>
public class ActionRollback : IAction
{
public char Letter => 'K';
public const char ActionLetter = 'K';
public char Letter => ActionLetter;
public string Alias => "rollback";
public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
public string Icon => "undo";

View File

@@ -1761,6 +1761,7 @@ namespace Umbraco.Web.Editors
: content.Variants.FirstOrDefault(x => x.Language.IsoCode == culture);
}
[EnsureUserPermissionForContent("contentId", ActionRollback.ActionLetter)]
[HttpPost]
public HttpResponseMessage PostRollbackContent(int contentId, int versionId, string culture = "*")
{

View File

@@ -52,7 +52,6 @@ namespace Umbraco.Web.Models.Trees
SeperatorBefore = false;
Icon = action.Icon;
Action = action;
OpensDialog = legacyMenu.OpensDialog;
}
#endregion
@@ -87,6 +86,9 @@ namespace Umbraco.Web.Models.Trees
[DataMember(Name = "cssclass")]
public string Icon { get; set; }
/// <summary>
/// Used in the UI to inform the user that the menu item will open a dialog/confirmation
/// </summary>
[DataMember(Name = "opensDialog")]
public bool OpensDialog { get; set; }

View File

@@ -62,7 +62,8 @@ namespace Umbraco.Web.Models.Trees
/// <typeparam name="T"></typeparam>
/// <param name="hasSeparator"></param>
/// <param name="textService">The <see cref="ILocalizedTextService"/> used to localize the action name based on it's alias</param>
public MenuItem Add<T>(ILocalizedTextService textService, bool hasSeparator = false)
/// <param name="opensDialog"></param>
public MenuItem Add<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
where T : IAction
{
var item = CreateMenuItem<T>(textService, hasSeparator);
@@ -87,7 +88,7 @@ namespace Umbraco.Web.Models.Trees
return menuItem;
}
internal MenuItem CreateMenuItem<T>(ILocalizedTextService textService, bool hasSeparator = false)
internal MenuItem CreateMenuItem<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
where T : IAction
{
var item = Current.Actions.GetAction<T>();
@@ -95,7 +96,8 @@ namespace Umbraco.Web.Models.Trees
var menuItem = new MenuItem(item, textService.Localize($"actions/{item.Alias}"))
{
SeperatorBefore = hasSeparator
SeperatorBefore = hasSeparator,
OpensDialog = opensDialog
};
return menuItem;

View File

@@ -93,7 +93,7 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
menu.Items.Add<ActionNew>(Services.TextService.Localize($"actions/{ActionNew.ActionAlias}"));
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -102,7 +102,7 @@ namespace Umbraco.Web.Trees
if (cte != null)
{
var ct = Services.ContentTypeService.Get(cte.Id);
var createItem = menu.Items.Add<ActionCreateBlueprintFromContent>(Services.TextService);
var createItem = menu.Items.Add<ActionCreateBlueprintFromContent>(Services.TextService, opensDialog: true);
createItem.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct.Alias);
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -110,7 +110,7 @@ namespace Umbraco.Web.Trees
return menu;
}
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
return menu;
}

View File

@@ -128,9 +128,8 @@ namespace Umbraco.Web.Trees
.Select(x => new MenuItem(x));
//these two are the standard items
//fixme: inject
menu.Items.Add<ActionNew>(Services.TextService.Localize("actions", ActionNew.ActionAlias));
menu.Items.Add<ActionSort>(Services.TextService.Localize("actions", Current.Actions.GetAction<ActionSort>().Alias), true);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionSort>(Services.TextService, true);
//filter the standard items
FilterUserAllowedMenuItems(menu, nodeActions);
@@ -226,25 +225,22 @@ namespace Umbraco.Web.Trees
protected MenuItemCollection GetAllNodeMenuItems(IUmbracoEntity item)
{
var menu = new MenuItemCollection();
AddActionNode<ActionNew>(item, menu);
AddActionNode<ActionDelete>(item, menu);
AddActionNode<ActionCreateBlueprintFromContent>(item, menu);
//need to ensure some of these are converted to the legacy system - until we upgrade them all to be angularized.
AddActionNode<ActionMove>(item, menu, true);
AddActionNode<ActionCopy>(item, menu);
AddActionNode<ActionNew>(item, menu, opensDialog: true);
AddActionNode<ActionDelete>(item, menu, opensDialog: true);
AddActionNode<ActionCreateBlueprintFromContent>(item, menu, opensDialog: true);
AddActionNode<ActionMove>(item, menu, true, opensDialog: true);
AddActionNode<ActionCopy>(item, menu, opensDialog: true);
AddActionNode<ActionSort>(item, menu, true);
AddActionNode<ActionAssignDomain>(item, menu);
AddActionNode<ActionRights>(item, menu);
AddActionNode<ActionProtect>(item, menu, true, true);
AddActionNode<ActionAssignDomain>(item, menu, opensDialog: true);
AddActionNode<ActionRights>(item, menu, opensDialog: true);
//fixme - conver this editor to angular
AddActionNode<ActionProtect>(item, menu, true, convert: true, opensDialog: true);
menu.Items.Add(new MenuItem("notify", Services.TextService)
{
Icon = "megaphone",
SeperatorBefore = true
SeperatorBefore = true,
OpensDialog = true
});
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -260,8 +256,8 @@ namespace Umbraco.Web.Trees
protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item)
{
var menu = new MenuItemCollection();
menu.Items.Add<ActionRestore>(Services.TextService.Localize("actions", ActionRestore.ActionAlias));
menu.Items.Add<ActionDelete>(Services.TextService.Localize("actions", ActionDelete.ActionAlias));
menu.Items.Add<ActionRestore>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -308,12 +304,13 @@ namespace Umbraco.Web.Trees
}
//fixme: Remove the need for converting to legacy
private void AddActionNode<TAction>(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false)
private void AddActionNode<TAction>(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false, bool opensDialog = false)
where TAction : IAction
{
//fixme: Inject
var menuItem = menu.Items.Add<TAction>(Services.TextService.Localize("actions", Current.Actions.GetAction<TAction>().Alias), hasSeparator);
if (convert) menuItem.ConvertLegacyMenuItem(item, "content", "content");
menuItem.OpensDialog = opensDialog;
}
////fixme: Remove the need for converting to legacy

View File

@@ -351,7 +351,8 @@ namespace Umbraco.Web.Trees
var menu = new MenuItemCollection();
menu.Items.Add(new MenuItem("emptyRecycleBin", Services.TextService)
{
Icon = "trash"
Icon = "trash",
OpensDialog = true
});
menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;

View File

@@ -81,11 +81,12 @@ namespace Umbraco.Web.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new MenuItem("importDocumentType", Services.TextService)
{
Icon = "page-up",
SeperatorBefore = true
SeperatorBefore = true,
OpensDialog = true
});
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -98,9 +99,9 @@ namespace Umbraco.Web.Trees
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename"))
menu.Items.Add(new MenuItem("rename", Services.TextService)
{
Icon = "icon icon-edit"
});
@@ -108,7 +109,7 @@ namespace Umbraco.Web.Trees
if (container.HasChildren == false)
{
//can delete doc type
menu.Items.Add<ActionDelete>(Services.TextService, true);
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
}
menu.Items.Add(new RefreshNode(Services.TextService, true));
}
@@ -119,20 +120,21 @@ namespace Umbraco.Web.Trees
if (enableInheritedDocumentTypes)
{
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
}
//no move action if this is a child doc type
if (parent == null)
{
menu.Items.Add<ActionMove>(Services.TextService, true);
menu.Items.Add<ActionMove>(Services.TextService, true, opensDialog: true);
}
menu.Items.Add<ActionCopy>(Services.TextService);
menu.Items.Add<ActionCopy>(Services.TextService, opensDialog: true);
menu.Items.Add(new MenuItem("export", Services.TextService)
{
Icon = "download-alt",
SeperatorBefore = true
SeperatorBefore = true,
OpensDialog = true
});
menu.Items.Add<ActionDelete>(Services.TextService, true);
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
if (enableInheritedDocumentTypes)
menu.Items.Add(new RefreshNode(Services.TextService, true));
}

View File

@@ -104,7 +104,7 @@ namespace Umbraco.Web.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
}
@@ -115,7 +115,7 @@ namespace Umbraco.Web.Trees
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename"))
{
@@ -125,7 +125,7 @@ namespace Umbraco.Web.Trees
if (container.HasChildren == false)
{
//can delete data type
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
}
menu.Items.Add(new RefreshNode(Services.TextService, true));
}
@@ -134,9 +134,9 @@ namespace Umbraco.Web.Trees
var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds();
if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id)) == false)
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionMove>(Services.TextService, hasSeparator: true);
menu.Items.Add<ActionMove>(Services.TextService, hasSeparator: true, opensDialog: true);
}
return menu;

View File

@@ -96,10 +96,10 @@ namespace Umbraco.Web.Trees
{
var menu = new MenuItemCollection();
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
if (id != Constants.System.Root.ToInvariantString())
menu.Items.Add<ActionDelete>(Services.TextService, true);
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
menu.Items.Add(new RefreshNode(Services.TextService, true));

View File

@@ -82,7 +82,7 @@ namespace Umbraco.Web.Trees
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//create action
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
//refresh action
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -96,7 +96,7 @@ namespace Umbraco.Web.Trees
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//create action
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any();
@@ -104,7 +104,7 @@ namespace Umbraco.Web.Trees
if (hasChildren == false)
{
//delete action
menu.Items.Add<ActionDelete>(Services.TextService, true);
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
}
//refresh action
@@ -118,7 +118,7 @@ namespace Umbraco.Web.Trees
var menu = new MenuItemCollection();
//if it's not a directory then we only allow to delete the item
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
return menu;
}

View File

@@ -59,7 +59,7 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
//Create the normal create action
menu.Items.Add<ActionNew>(Services.TextService)
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true)
//Since we haven't implemented anything for macros in angular, this needs to be converted to
//use the legacy format
.ConvertLegacyMenuItem(null, "initmacros", queryStrings.GetValue<string>("application"));
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Trees
if (macro == null) return new MenuItemCollection();
//add delete option for all macros
menu.Items.Add<ActionDelete>(Services.TextService)
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true)
//Since we haven't implemented anything for macros in angular, this needs to be converted to
//use the legacy format
.ConvertLegacyMenuItem(new EntitySlim

View File

@@ -95,7 +95,7 @@ namespace Umbraco.Web.Trees
}
// root actions
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionSort>(Services.TextService, true);
menu.Items.Add(new RefreshNode(Services.TextService, true));
return menu;
@@ -119,9 +119,9 @@ namespace Umbraco.Web.Trees
}
//return a normal node menu:
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionMove>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionMove>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionSort>(Services.TextService);
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -129,7 +129,10 @@ namespace Umbraco.Web.Trees
if (item.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString()))
{
menu.DefaultMenuAlias = null;
menu.Items.Insert(2, new MenuItem(Current.Actions.GetAction<ActionRestore>(), Services.TextService.Localize("actions", ActionRestore.ActionAlias)));
menu.Items.Insert(2, new MenuItem(ActionRestore.ActionAlias, Services.TextService)
{
OpensDialog = true
});
}
else
{

View File

@@ -74,7 +74,7 @@ namespace Umbraco.Web.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new RefreshNode(Services.TextService));
return menu;
}
@@ -85,7 +85,7 @@ namespace Umbraco.Web.Trees
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
menu.Items.Add(new MenuItem("rename", Services.TextService.Localize("actions/rename"))
{
@@ -95,7 +95,7 @@ namespace Umbraco.Web.Trees
if (container.HasChildren == false)
{
//can delete doc type
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
}
menu.Items.Add(new RefreshNode(Services.TextService, true));
}
@@ -106,26 +106,26 @@ namespace Umbraco.Web.Trees
if (enableInheritedMediaTypes)
{
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
//no move action if this is a child doc type
if (parent == null)
{
menu.Items.Add<ActionMove>(Services.TextService, true);
menu.Items.Add<ActionMove>(Services.TextService, true, opensDialog: true);
}
}
else
{
menu.Items.Add<ActionMove>(Services.TextService);
menu.Items.Add<ActionMove>(Services.TextService, opensDialog: true);
//no move action if this is a child doc type
if (parent == null)
{
menu.Items.Add<ActionMove>(Services.TextService, true);
menu.Items.Add<ActionMove>(Services.TextService, true, opensDialog: true);
}
}
menu.Items.Add<ActionCopy>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionCopy>(Services.TextService, opensDialog: true);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
if (enableInheritedMediaTypes)
menu.Items.Add(new RefreshNode(Services.TextService, true));
}

View File

@@ -159,17 +159,16 @@ namespace Umbraco.Web.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//Create the normal create action
menu.Items.Add<ActionNew>(Services.TextService);
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
}
else
{
//Create a custom create action - this does not launch a dialog, it just navigates to the create screen
// we'll create it based on the ActionNew so it maintains the same icon properties, name, etc...
var createMenuItem = new MenuItem
var createMenuItem = new MenuItem(ActionNew.ActionAlias, Services.TextService)
{
Name = Services.TextService.Localize($"actions/{ActionNew.ActionAlias}"),
Alias = ActionNew.ActionAlias,
Icon = "add"
Icon = "add",
OpensDialog = true
};
//we want to go to this route: /member/member/edit/-1?create=true
createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true");
@@ -181,7 +180,7 @@ namespace Umbraco.Web.Trees
}
//add delete option for all members
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
if (Security.CurrentUser.HasAccessToSensitiveData())
{

View File

@@ -33,7 +33,7 @@ namespace Umbraco.Web.Trees
else
{
//delete member type/group
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
}
return menu;

View File

@@ -84,12 +84,12 @@ namespace Umbraco.Web.Trees
// Root actions
if (id == "-1")
{
menu.Items.Add<ActionNew>(Services.TextService)
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true)
.ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue<string>("application"));
}
else if (id == "created")
{
menu.Items.Add<ActionNew>(Services.TextService)
menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true)
.ConvertLegacyMenuItem(null, Constants.Trees.Packages, queryStrings.GetValue<string>("application"));
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -97,7 +97,7 @@ namespace Umbraco.Web.Trees
else
{
//it's a package node
menu.Items.Add<ActionDelete>(Services.TextService);
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true);
}
return menu;

View File

@@ -25,7 +25,7 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.Root.ToInvariantString())
{
//Create the normal create action
var addMenuItem = menu.Items.Add<ActionNew>(Services.TextService);
var addMenuItem = menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
addMenuItem.LaunchDialogUrl("developer/RelationTypes/NewRelationType.aspx", "Create New RelationType");
//refresh action
menu.Items.Add(new RefreshNode(Services.TextService, true));
@@ -37,7 +37,7 @@ namespace Umbraco.Web.Trees
if (relationType == null) return new MenuItemCollection();
//add delete option for all macros
menu.Items.Add<ActionDelete>(Services.TextService)
menu.Items.Add<ActionDelete>(Services.TextService, opensDialog: true)
//Since we haven't implemented anything for relationtypes in angular, this needs to be converted to
//use the legacy format
.ConvertLegacyMenuItem(new EntitySlim

View File

@@ -70,7 +70,7 @@ namespace Umbraco.Web.Trees
var menu = new MenuItemCollection();
//Create the normal create action
var item = menu.Items.Add<ActionNew>(Services.TextService);
var item = menu.Items.Add<ActionNew>(Services.TextService, opensDialog: true);
item.NavigateToRoute($"{queryStrings.GetValue<string>("application")}/templates/edit/{id}?create=true");
if (id == Constants.System.Root.ToInvariantString())
@@ -89,7 +89,7 @@ namespace Umbraco.Web.Trees
if (template.IsMasterTemplate == false)
{
//add delete option if it doesn't have children
menu.Items.Add<ActionDelete>(Services.TextService, true);
menu.Items.Add<ActionDelete>(Services.TextService, true, opensDialog: true);
}
//add refresh