Support SVG icon in action menu (#12403)

* Support custom SVG icon in menu item with legacy support

* Update menu icons

* Update action icons

* Adjust icons in menu actions with legacy fallback

* Don't use legacy icon

* Update comments
This commit is contained in:
Bjarne Fyrstenborg
2022-05-16 23:50:19 +02:00
committed by GitHub
parent 048193e3a5
commit d051f850eb
39 changed files with 244 additions and 189 deletions

View File

@@ -23,7 +23,7 @@ public class ActionAssignDomain : IAction
public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
/// <inheritdoc/>
public string Icon => "home";
public string Icon => "icon-home";
/// <inheritdoc/>
public bool ShowInNotifier => false;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
/// <inheritdoc/>
public string Icon => "documents";
public string Icon => "icon-documents";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Actions
public bool CanBePermissionAssigned => true;
/// <inheritdoc/>
public string Icon => "blueprint";
public string Icon => Constants.Icons.Blueprint;
/// <inheritdoc/>
public string Alias => "createblueprint";

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -28,7 +28,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
/// <inheritdoc/>
public string Icon => "delete";
public string Icon => "icon-delete";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
/// <inheritdoc/>
public string Icon => "enter";
public string Icon => "icon-enter";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Actions
public string Alias => ActionAlias;
/// <inheritdoc/>
public string Icon => "add";
public string Icon => "icon-add";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -18,7 +18,7 @@ namespace Umbraco.Cms.Core.Actions
public bool CanBePermissionAssigned => true;
/// <inheritdoc/>
public string Icon => "megaphone";
public string Icon => "icon-megaphone";
/// <inheritdoc/>
public string Alias => "notify";

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
/// <inheritdoc/>
public string Icon => "lock";
public string Icon => "icon-lock";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string? Category => null;
/// <inheritdoc/>
public string Icon => "undo";
public string Icon => "icon-undo";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
/// <inheritdoc/>
public string Icon => "vcard";
public string Icon => "icon-vcard";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.AdministrationCategory;
/// <inheritdoc/>
public string Icon => "undo";
public string Icon => "icon-undo";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.StructureCategory;
/// <inheritdoc/>
public string Icon => "navigation-vertical";
public string Icon => "icon-navigation-vertical";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
/// <inheritdoc/>
public string Icon => "outbox";
public string Icon => "icon-outbox";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
/// <inheritdoc/>
public string Icon => "circle-dotted";
public string Icon => "icon-circle-dotted";
/// <inheritdoc/>
public bool ShowInNotifier => false;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.
namespace Umbraco.Cms.Core.Actions
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Actions
public string Category => Constants.Conventions.PermissionCategories.ContentCategory;
/// <inheritdoc/>
public string Icon => "save";
public string Icon => "icon-save";
/// <inheritdoc/>
public bool ShowInNotifier => true;

View File

@@ -1,27 +1,32 @@
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Core.Models.Trees
{
/// <summary>
/// Represents the refresh node menu item
/// Represents the refresh node menu item.
/// </summary>
public sealed class CreateChildEntity : ActionMenuItem
{
private const string icon = "icon-add";
public override string AngularServiceName => "umbracoMenuActions";
public CreateChildEntity(string name, bool separatorBefore = false)
: base(ActionNew.ActionAlias, name)
{
Icon = "add"; Name = name;
Icon = icon;
Name = name;
SeparatorBefore = separatorBefore;
UseLegacyIcon = false;
}
public CreateChildEntity(ILocalizedTextService textService, bool separatorBefore = false)
: base(ActionNew.ActionAlias, textService)
{
Icon = "add";
Icon = icon;
SeparatorBefore = separatorBefore;
UseLegacyIcon = false;
}
}
}

View File

@@ -1,9 +1,9 @@
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Core.Models.Trees
{
/// <summary>
/// Represents the export member menu item
/// Represents the export member menu item.
/// </summary>
public sealed class ExportMember : ActionMenuItem
{
@@ -12,6 +12,7 @@ namespace Umbraco.Cms.Core.Models.Trees
public ExportMember(ILocalizedTextService textService) : base("export", textService)
{
Icon = "download-alt";
UseLegacyIcon = false;
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using System.Threading;
@@ -10,7 +10,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.Models.Trees
{
/// <summary>
/// A context menu item
/// A context menu item.
/// </summary>
[DataContract(Name = "menuItem", Namespace = "")]
public class MenuItem
@@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models.Trees
public MenuItem()
{
AdditionalData = new Dictionary<string, object>();
Icon = "folder";
Icon = Constants.Icons.Folder;
}
public MenuItem(string alias, string name)
@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Models.Trees
}
/// <summary>
/// Create a menu item based on an <see cref="IAction"/> definition
/// Create a menu item based on an <see cref="IAction"/> definition.
/// </summary>
/// <param name="action"></param>
/// <param name="name"></param>
@@ -80,16 +80,25 @@ namespace Umbraco.Cms.Core.Models.Trees
public string? TextDescription { get; set; }
/// <summary>
/// Ensures a menu separator will exist before this menu item
/// Ensures a menu separator will exist before this menu item.
/// </summary>
[DataMember(Name = "separator")]
public bool SeparatorBefore { get; set; }
[DataMember(Name = "cssclass")]
/// <summary>
/// Icon to use at action menu item.
/// </summary>
[DataMember(Name = "icon")]
public string Icon { get; set; }
/// Used in the UI to indicate whether icons should be prefixed with "icon-".
/// If not legacy icon full icon name should be specified.
/// </summary>
[DataMember(Name = "useLegacyIcon")]
public bool UseLegacyIcon { get; set; } = true;
/// <summary>
/// Used in the UI to inform the user that the menu item will open a dialog/confirmation
/// 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

@@ -1,27 +1,31 @@
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Core.Models.Trees
{
/// <inheritdoc />
/// <summary>
/// Represents the refresh node menu item
/// Represents the refresh node menu item.
/// </summary>
public sealed class RefreshNode : ActionMenuItem
{
private const string icon = "icon-refresh";
public override string AngularServiceName => "umbracoMenuActions";
public RefreshNode(string name, bool separatorBefore = false)
: base("refreshNode", name)
{
Icon = "refresh";
Icon = icon;
SeparatorBefore = separatorBefore;
UseLegacyIcon = false;
}
public RefreshNode(ILocalizedTextService textService, bool separatorBefore = false)
: base("refreshNode", textService)
{
Icon = "refresh";
Icon = icon;
SeparatorBefore = separatorBefore;
UseLegacyIcon = false;
}
}
}

View File

@@ -38,10 +38,11 @@ namespace Umbraco.Cms.Core.Trees
/// <param name="hasSeparator"></param>
/// <param name="textService">The <see cref="ILocalizedTextService"/> used to localize the action name based on its alias</param>
/// <param name="opensDialog">Whether or not this action opens a dialog</param>
public MenuItem? Add<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
/// <param name="useLegacyIcon">Whether or not this action should use legacy icon prefixed with "icon-" or full icon name is specified.</param>
public MenuItem? Add<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false, bool useLegacyIcon = true)
where T : IAction
{
var item = CreateMenuItem<T>(textService, hasSeparator, opensDialog);
var item = CreateMenuItem<T>(textService, hasSeparator, opensDialog, useLegacyIcon);
if (item != null)
{
Add(item);
@@ -50,7 +51,7 @@ namespace Umbraco.Cms.Core.Trees
return null;
}
private MenuItem? CreateMenuItem<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false)
private MenuItem? CreateMenuItem<T>(ILocalizedTextService textService, bool hasSeparator = false, bool opensDialog = false, bool useLegacyIcon = true)
where T : IAction
{
var item = _actionCollection.GetAction<T>();
@@ -59,11 +60,12 @@ namespace Umbraco.Cms.Core.Trees
var values = textService.GetAllStoredValues(Thread.CurrentThread.CurrentUICulture);
values.TryGetValue($"visuallyHiddenTexts/{item.Alias}Description", out var textDescription);
var menuItem = new MenuItem(item, textService.Localize($"actions", item.Alias))
var menuItem = new MenuItem(item, textService.Localize("actions", item.Alias))
{
SeparatorBefore = hasSeparator,
OpensDialog = opensDialog,
TextDescription = textDescription,
UseLegacyIcon = useLegacyIcon,
};
return menuItem;

View File

@@ -135,7 +135,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
@@ -145,7 +145,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (cte != null)
{
var ct = _contentTypeService.Get(cte.Id);
var createItem = menu.Items.Add<ActionCreateBlueprintFromContent>(LocalizedTextService, opensDialog: true);
var createItem = menu.Items.Add<ActionCreateBlueprintFromContent>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
createItem?.NavigateToRoute("/settings/contentBlueprints/edit/-1?create=true&doctype=" + ct?.Alias);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
@@ -153,7 +153,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return menu;
}
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
return menu;
}

View File

@@ -169,8 +169,8 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
.Select(x => new MenuItem(x));
//these two are the standard items
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionSort>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionSort>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
//filter the standard items
FilterUserAllowedMenuItems(menu, nodeActions);
@@ -271,23 +271,24 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
protected MenuItemCollection GetAllNodeMenuItems(IUmbracoEntity item)
{
var menu = _menuItemCollectionFactory.Create();
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, opensDialog: true);
AddActionNode<ActionAssignDomain>(item, menu, opensDialog: true);
AddActionNode<ActionRights>(item, menu, opensDialog: true);
AddActionNode<ActionProtect>(item, menu, true, opensDialog: true);
AddActionNode<ActionNew>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionDelete>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionCreateBlueprintFromContent>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionMove>(item, menu, true, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionCopy>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionSort>(item, menu, true, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionAssignDomain>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionRights>(item, menu, opensDialog: true, useLegacyIcon: false);
AddActionNode<ActionProtect>(item, menu, true, opensDialog: true, useLegacyIcon: false);
if (_emailSender.CanSendRequiredEmail())
{
menu.Items.Add(new MenuItem("notify", LocalizedTextService)
{
Icon = "megaphone",
Icon = "icon-megaphone",
SeparatorBefore = true,
OpensDialog = true
OpensDialog = true,
UseLegacyIcon = false,
});
}
@@ -307,9 +308,9 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
protected MenuItemCollection GetNodeMenuItemsForDeletedContent(IUmbracoEntity item)
{
var menu = _menuItemCollectionFactory.Create();
menu.Items.Add<ActionRestore>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionRestore>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
@@ -361,10 +362,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
}
private void AddActionNode<TAction>(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool opensDialog = false)
private void AddActionNode<TAction>(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool opensDialog = false, bool useLegacyIcon = true)
where TAction : IAction
{
var menuItem = menu.Items.Add<TAction>(LocalizedTextService, hasSeparator, opensDialog);
var menuItem = menu.Items.Add<TAction>(LocalizedTextService, hasSeparator, opensDialog, useLegacyIcon);
}
public async Task<EntitySearchResults> SearchAsync(string query, int pageSize, long pageIndex, string? searchFrom = null)

View File

@@ -471,14 +471,17 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
var menu = MenuItemCollectionFactory.Create();
// only add empty recycle bin if the current user is allowed to delete by default
if (deleteAllowed)
{
menu.Items.Add(new MenuItem("emptyrecyclebin", LocalizedTextService)
{
Icon = "trash",
OpensDialog = true
Icon = "icon-trash",
OpensDialog = true,
UseLegacyIcon = false,
});
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
return menu;

View File

@@ -119,17 +119,19 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new MenuItem("importdocumenttype", LocalizedTextService)
{
Icon = "page-up",
Icon = "icon-page-up",
SeparatorBefore = true,
OpensDialog = true
OpensDialog = true,
UseLegacyIcon = false,
});
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -138,21 +140,23 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var container = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.DocumentTypeContainer);
if (container != null)
{
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new MenuItem("rename", LocalizedTextService)
{
Icon = "icon icon-edit"
Icon = "icon-edit",
UseLegacyIcon = false,
});
if (container.HasChildren == false)
{
//can delete doc type
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
// can delete doc type
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
else
@@ -160,22 +164,25 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var ct = _contentTypeService.Get(int.Parse(id, CultureInfo.InvariantCulture));
var parent = ct == null ? null : _contentTypeService.Get(ct.ParentId);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
//no move action if this is a child doc type
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
// no move action if this is a child doc type
if (parent == null)
{
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new MenuItem("export", LocalizedTextService)
{
Icon = "download-alt",
Icon = "icon-download-alt",
SeparatorBefore = true,
OpensDialog = true
OpensDialog = true,
UseLegacyIcon = false,
});
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
return menu;

View File

@@ -133,7 +133,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
@@ -141,21 +141,23 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var container = _entityService.Get(int.Parse(id, CultureInfo.InvariantCulture), UmbracoObjectTypes.DataTypeContainer);
if (container != null)
{
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new MenuItem("rename", LocalizedTextService.Localize("actions", "rename"))
{
Icon = "icon icon-edit"
Icon = "icon-edit",
UseLegacyIcon = false,
});
if (container.HasChildren == false)
{
//can delete data type
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
// can delete data type
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
else
@@ -163,9 +165,11 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var nonDeletableSystemDataTypeIds = GetNonDeletableSystemDataTypeIds();
if (nonDeletableSystemDataTypeIds.Contains(int.Parse(id, CultureInfo.InvariantCulture)) == false)
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
{
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add<ActionMove>(LocalizedTextService, hasSeparator: true, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, hasSeparator: true, opensDialog: true, useLegacyIcon: false);
}
return menu;

View File

@@ -126,15 +126,14 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
{
var menu = _menuItemCollectionFactory.Create();
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
if (id != Constants.System.RootString)
{
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;

View File

@@ -65,10 +65,14 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var hasChildren = FileSystem is not null && (FileSystem.GetFiles(directory).Any() || FileSystem.GetDirectories(directory).Any());
var name = Path.GetFileName(directory);
var node = CreateTreeNode(WebUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren);
var node = CreateTreeNode(WebUtility.UrlEncode(directory), path, queryStrings, name, Constants.Icons.Folder, hasChildren);
OnRenderFolderNode(ref node);
if (node != null)
{
nodes.Add(node);
}
}
}
@@ -94,9 +98,13 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var name = Path.GetFileName(file);
var node = CreateTreeNode(WebUtility.UrlEncode(file), path, queryStrings, name, FileIcon, false);
OnRenderFileNode(ref node);
if (node != null)
{
nodes.Add(node);
}
}
}
@@ -112,8 +120,9 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
var root = rootResult.Value;
//check if there are any children
// check if there are any children
var treeNodesResult = GetTreeNodes(Constants.System.RootString, queryStrings);
if (!(treeNodesResult.Result is null))
{
return treeNodesResult.Result;
@@ -132,11 +141,13 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
{
var menu = MenuItemCollectionFactory.Create();
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
//refresh action
// create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
// refresh action
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -146,21 +157,22 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
{
var menu = MenuItemCollectionFactory.Create();
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
// create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
var hasChildren = FileSystem is not null && (FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any());
//We can only delete folders if it doesn't have any children (folders or files)
// We can only delete folders if it doesn't have any children (folders or files)
if (hasChildren == false)
{
//delete action
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
// delete action
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
//refresh action
// refresh action
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -170,8 +182,8 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
{
var menu = MenuItemCollectionFactory.Create();
//if it's not a directory then we only allow to delete the item
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
// if it's not a directory then we only allow to delete the item
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
return menu;
}

View File

@@ -75,10 +75,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
//Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService);
// Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService, useLegacyIcon: false);
//refresh action
// refresh action
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -87,8 +87,8 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var macro = _macroService.GetById(int.Parse(id, CultureInfo.InvariantCulture));
if (macro == null) return menu;
//add delete option for all macros
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
// add delete option for all macros
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
return menu;
}

View File

@@ -118,9 +118,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionSort>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionSort>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
@@ -134,7 +135,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
return NotFound();
}
//if the user has no path access for this node, all they can do is refresh
// if the user has no path access for this node, all they can do is refresh
if (!_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.HasMediaPathAccess(item, _entityService, _appCaches) ?? false)
{
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
@@ -142,27 +143,26 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
//if the media item is in the recycle bin, we don't have a default menu and we need to show a limited menu
// if the media item is in the recycle bin, we don't have a default menu and we need to show a limited menu
if (item.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString()))
{
menu.Items.Add<ActionRestore>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionRestore>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
menu.DefaultMenuAlias = null;
}
else
{
//return a normal node menu:
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionSort>(LocalizedTextService);
// return a normal node menu:
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add<ActionSort>(LocalizedTextService, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
//set the default to create
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
}
@@ -172,7 +172,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
protected override UmbracoObjectTypes UmbracoObjectType => UmbracoObjectTypes.Media;
/// <summary>
/// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access
/// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access.
/// </summary>
/// <param name="id"></param>
/// <param name="queryStrings"></param>

View File

@@ -96,7 +96,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
menu.DefaultMenuAlias = ActionNew.ActionAlias;
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService));
return menu;
}
@@ -107,17 +107,18 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
// set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new MenuItem("rename", LocalizedTextService.Localize("actions", "rename"))
{
Icon = "icon icon-edit"
Icon = "icon-edit",
UseLegacyIcon = false
});
if (container.HasChildren == false)
{
// can delete doc type
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
@@ -126,21 +127,21 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var ct = _mediaTypeService.Get(int.Parse(id, CultureInfo.InvariantCulture));
var parent = ct == null ? null : _mediaTypeService.Get(ct.ParentId);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
// no move action if this is a child doc type
if (parent == null)
{
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
if(ct?.IsSystemMediaType() == false)
{
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
}
return menu;

View File

@@ -53,7 +53,6 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
}
protected override IEnumerable<TreeNode> GetTreeNodesFromService(string id, FormCollection queryStrings)
=> _memberGroupService.GetAll()
.OrderBy(x => x.Name)

View File

@@ -96,7 +96,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
member.Name,
Constants.Icons.Member,
false,
"",
string.Empty,
Udi.Create(ObjectTypes.GetUdiType(Constants.ObjectTypes.Member), member.Key));
node.AdditionalData.Add("contentType", member.ContentTypeAlias);
@@ -121,9 +121,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
queryStrings.GetRequiredValue<string>("application") + TreeAlias.EnsureStartsWith('/') + "/list/" + memberType.Alias)));
}
//There is no menu for any of these nodes
// There is no menu for any of these nodes
nodes.ForEach(x => x.MenuUrl = null);
//All nodes are containers
// All nodes are containers
nodes.ForEach(x => x.AdditionalData.Add("isContainer", true));
return nodes;
@@ -136,18 +137,19 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
// root actions
//set default
// set default
menu.DefaultMenuAlias = ActionNew.ActionAlias;
//Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
// Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
//add delete option for all members
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
// add delete option for all members
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
if (_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.HasAccessToSensitiveData() ?? false)
{

View File

@@ -80,11 +80,11 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
var memberType = _memberTypeService.Get(int.Parse(id));
if (memberType != null)
{
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionCopy>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
// delete member type/group
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
}
return menu;

View File

@@ -43,10 +43,10 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
//Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService);
// Create the normal create action
menu.Items.Add<ActionNew>(LocalizedTextService, useLegacyIcon: false);
//refresh action
// refresh action
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -57,7 +57,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (relationType.IsSystemRelationType() == false)
{
menu.Items.Add<ActionDelete>(LocalizedTextService);
menu.Items.Add<ActionDelete>(LocalizedTextService, useLegacyIcon: false);
}
return menu;
@@ -70,8 +70,7 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (id == Constants.System.RootString)
{
nodes.AddRange(_relationService.GetAllRelationTypes()
.Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name,
"icon-trafic", false)));
.Select(rt => CreateTreeNode(rt.Id.ToString(), id, queryStrings, rt.Name, "icon-trafic", false)));
}
return nodes;

View File

@@ -111,13 +111,13 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
{
var menu = _menuItemCollectionFactory.Create();
//Create the normal create action
var item = menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
// Create the normal create action
var item = menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true, useLegacyIcon: false);
item?.NavigateToRoute($"{queryStrings.GetRequiredValue<string>("application")}/templates/edit/{id}?create=true");
if (id == Constants.System.RootString)
{
//refresh action
// refresh action
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
@@ -127,17 +127,16 @@ namespace Umbraco.Cms.Web.BackOffice.Trees
if (template == null) return menu;
var entity = FromTemplate(template);
//don't allow delete if it has child layouts
// don't allow delete if it has child layouts
if (template.IsMasterTemplate == false)
{
//add delete option if it doesn't have children
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true);
// add delete option if it doesn't have children
menu.Items.Add<ActionDelete>(LocalizedTextService, true, opensDialog: true, useLegacyIcon: false);
}
//add refresh
// add refresh
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}

View File

@@ -7,7 +7,7 @@
* Handles the click events on the context menu
**/
angular.module("umbraco.directives")
.directive('umbContextMenu', function (navigationService, keyboardService, backdropService) {
.directive('umbContextMenu', function (navigationService, keyboardService) {
return {
scope: {
menuDialogTitle: "@",
@@ -20,22 +20,27 @@ angular.module("umbraco.directives")
templateUrl: 'views/components/application/umb-contextmenu.html',
link: function (scope, element, attrs, ctrl) {
// Map action icons using legacy icon font or svg icons.
Utilities.forEach(scope.menuActions, action => {
action.icon = (action.useLegacyIcon ? 'icon-' : '') + action.icon;
});
//adds a handler to the context menu item click, we need to handle this differently
//depending on what the menu item is supposed to do.
scope.executeMenuItem = function (action) {
scope.executeMenuItem = action => {
navigationService.executeMenuAction(action, scope.currentNode, scope.currentSection);
};
scope.outSideClick = function() {
scope.outSideClick = () => {
navigationService.hideNavigation();
};
keyboardService.bind("esc", function() {
keyboardService.bind("esc", () => {
navigationService.hideNavigation();
});
//ensure to unregister from all events!
scope.$on('$destroy', function () {
scope.$on('$destroy', () => {
keyboardService.unbind("esc");
});
}

View File

@@ -1,7 +1,7 @@
(function () {
'use strict';
function EditorMenuDirective($injector, treeService, navigationService, umbModelMapper, appState) {
function EditorMenuDirective(treeService, navigationService, appState) {
function link(scope, el, attr, ctrl) {
@@ -17,7 +17,7 @@
//adds a handler to the context menu item click, we need to handle this differently
//depending on what the menu item is supposed to do.
scope.executeMenuItem = function (action) {
scope.executeMenuItem = action => {
//the action is called as it would be by the tree. to ensure that the action targets the correct node,
//we need to set the current node in appState before calling the action. otherwise we break all actions
//that use the current node (and that's pretty much all of them)
@@ -34,10 +34,14 @@
}
if (!scope.actions) {
treeService.getMenu({ treeNode: scope.currentNode })
.then(function (data) {
scope.actions = data.menuItems;
treeService.getMenu({ treeNode: scope.currentNode }).then(data => {
scope.actions = data.menuItems;
// Map action icons using legacy icon font or svg icons.
Utilities.forEach(scope.actions, action => {
action.icon = (action.useLegacyIcon ? 'icon-' : '') + action.icon;
});
});
}
};

View File

@@ -14,7 +14,7 @@
ng-class="{sep:action.separator, '-opens-dialog': action.opensDialog}" ng-repeat="action in menuActions">
<button type="button" ng-click="executeMenuItem(action)"
class="umb-action-link btn-reset umb-outline">
<umb-icon icon="icon-{{action.cssclass}}" class="icon"></umb-icon>
<umb-icon icon="{{action.icon}}" class="icon"></umb-icon>
<span class="menu-label">{{action.name}}</span>
</button>
</li>

View File

@@ -8,14 +8,13 @@
show-caret="true"
has-popup="true"
is-expanded="dropdown.isOpen"
disabled="!actions || !actions.length || isDisabled"
>
disabled="!actions || !actions.length || isDisabled">
</umb-button>
<umb-dropdown ng-if="dropdown.isOpen" class="umb-actions" on-close="dropdown.isOpen = false" deep-blur="dropdown.isOpen = false">
<umb-dropdown-item class="umb-action" ng-class="{'sep':action.separatorm, '-opens-dialog': action.opensDialog}" ng-repeat="action in actions">
<umb-dropdown-item class="umb-action" ng-class="{'sep': action.separator, '-opens-dialog': action.opensDialog}" ng-repeat="action in actions">
<button type="button" ng-click="executeMenuItem(action)">
<umb-icon icon="icon-{{action.cssclass}}" class="icon"></umb-icon>
<umb-icon icon="{{action.icon}}" class="icon"></umb-icon>
<!-- Render the text that will be visually displayed -->
<span class="menu-label" aria-hidden="true">{{action.name}}</span>
<!-- Render the textDescription from the language files if it's attached to the action object-->