mirror of https://github.com/abpframework/abp.git
18 changed files with 499 additions and 10 deletions
@ -0,0 +1,26 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Ui.Navigation; |
||||
|
|
||||
|
namespace AbpDesk.Web.Mvc.Navigation |
||||
|
{ |
||||
|
public class MainMenuContributor : IMenuContributor |
||||
|
{ |
||||
|
public Task ConfigureMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Menu.Name != StandardMenus.Main) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
context.Menu.DisplayName = "Main Menu"; |
||||
|
|
||||
|
context.Menu.AddItem( |
||||
|
new ApplicationMenuItem("TicketManagement", "Ticket Management") |
||||
|
.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management")) |
||||
|
.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management")) |
||||
|
); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
@using System.Threading.Tasks |
||||
|
@model Volo.Abp.Ui.Navigation.ApplicationMenu |
||||
|
<h2>@Model.DisplayName</h2> |
||||
|
<ul> |
||||
|
@foreach (var menuItem in Model.Items) |
||||
|
{ |
||||
|
<li> |
||||
|
<a href="@menuItem.Url">@menuItem.DisplayName</a> |
||||
|
@if (menuItem.Items.Any()) |
||||
|
{ |
||||
|
<ul> |
||||
|
@foreach (var childMenuItem in menuItem.Items) |
||||
|
{ |
||||
|
<li> |
||||
|
<a href="@childMenuItem.Url">@childMenuItem.DisplayName</a> |
||||
|
</li> |
||||
|
} |
||||
|
</ul> |
||||
|
} |
||||
|
</li> |
||||
|
} |
||||
|
</ul> |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Ui.Navigation; |
||||
|
|
||||
|
namespace AbpDesk.Web.Mvc.Views.Shared.Components.HorizontalMenu |
||||
|
{ |
||||
|
public class HorizontalMenuViewComponent : ViewComponent |
||||
|
{ |
||||
|
private readonly IMenuManager _menuManager; |
||||
|
|
||||
|
public HorizontalMenuViewComponent(IMenuManager menuManager) |
||||
|
{ |
||||
|
//TODO: Create a INavigationAppService that can also be used remotely, instead of directly using IMenuManager!
|
||||
|
|
||||
|
_menuManager = menuManager; |
||||
|
} |
||||
|
|
||||
|
public async Task<IViewComponentResult> InvokeAsync(string menuName = StandardMenus.Main) |
||||
|
{ |
||||
|
var menu = await _menuManager.GetAsync(StandardMenus.Main); |
||||
|
return View(menu); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class ApplicationMenu : IHasMenuItems |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Unique name of the menu in the application.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display name of the menu.
|
||||
|
/// Default value is the <see cref="Name"/>.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string DisplayName |
||||
|
{ |
||||
|
get { return _displayName; } |
||||
|
set |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(value, nameof(value)); |
||||
|
_displayName = value; |
||||
|
} |
||||
|
} |
||||
|
private string _displayName; |
||||
|
|
||||
|
/// <inheritdoc cref="IHasMenuItems.Items"/>
|
||||
|
[NotNull] |
||||
|
public IList<ApplicationMenuItem> Items { get; } //TODO: Create a specialized collection (that can contain AddAfter for example)
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can be used to store a custom object related to this menu.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public object CustomData { get; set; } |
||||
|
|
||||
|
public ApplicationMenu( |
||||
|
[NotNull] string name, |
||||
|
string displayName = null) |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
|
||||
|
Name = name; |
||||
|
DisplayName = displayName ?? Name; |
||||
|
|
||||
|
Items = new List<ApplicationMenuItem>(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds a <see cref="ApplicationMenuItem"/> to <see cref="Items"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="menuItem"><see cref="ApplicationMenuItem"/> to be added</param>
|
||||
|
/// <returns>This <see cref="ApplicationMenu"/> object</returns>
|
||||
|
public ApplicationMenu AddItem([NotNull] ApplicationMenuItem menuItem) |
||||
|
{ |
||||
|
Items.Add(menuItem); |
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,108 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.ExtensionMethods.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class ApplicationMenuItem : IHasMenuItems |
||||
|
{ |
||||
|
private string _displayName; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Default <see cref="Order"/> value of a menu item.
|
||||
|
/// </summary>
|
||||
|
public const int DefaultOrder = 1000; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Unique name of the menu in the application.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display name of the menu item.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string DisplayName |
||||
|
{ |
||||
|
get { return _displayName; } |
||||
|
set |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(value, nameof(value)); |
||||
|
_displayName = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The Display order of the menu.
|
||||
|
/// Default value: 1000.
|
||||
|
/// </summary>
|
||||
|
public int Order { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The URL to navigate when this menu item is selected.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Url { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Icon of the menu item if exists.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Icon { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns true if this menu item has no child <see cref="Items"/>.
|
||||
|
/// </summary>
|
||||
|
public bool IsLeaf => Items.IsNullOrEmpty(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Target of the menu item. Can be null, "_blank", "_self", "_parent", "_top" or a frame name for web applications.
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Target { get; set; } |
||||
|
|
||||
|
/// <inheritdoc cref="IHasMenuItems.Items"/>
|
||||
|
[NotNull] |
||||
|
public IList<ApplicationMenuItem> Items { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Can be used to store a custom object related to this menu item. Optional.
|
||||
|
/// </summary>
|
||||
|
public object CustomData { get; set; } |
||||
|
|
||||
|
public ApplicationMenuItem( |
||||
|
[NotNull] string name, |
||||
|
[NotNull] string displayName, |
||||
|
string url = null, |
||||
|
string icon = null, |
||||
|
int order = DefaultOrder, |
||||
|
object customData = null, |
||||
|
string target = null) |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
Check.NotNullOrWhiteSpace(displayName, nameof(displayName)); |
||||
|
|
||||
|
Name = name; |
||||
|
DisplayName = displayName; |
||||
|
Url = url; |
||||
|
Icon = icon; |
||||
|
Order = order; |
||||
|
CustomData = customData; |
||||
|
Target = target; |
||||
|
|
||||
|
Items = new List<ApplicationMenuItem>(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds a <see cref="ApplicationMenuItem"/> to <see cref="Items"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="menuItem"><see cref="ApplicationMenuItem"/> to be added</param>
|
||||
|
/// <returns>This <see cref="ApplicationMenuItem"/> object</returns>
|
||||
|
public ApplicationMenuItem AddItem([NotNull] ApplicationMenuItem menuItem) |
||||
|
{ |
||||
|
Items.Add(menuItem); |
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public interface IHasMenuItems |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Menu items.
|
||||
|
/// </summary>
|
||||
|
IList<ApplicationMenuItem> Items { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public interface IMenuConfigurationContext : IServiceProviderAccessor |
||||
|
{ |
||||
|
ApplicationMenu Menu { get; set; } |
||||
|
|
||||
|
//TODO: Add Localization, Authorization components since they are most used components on menu creation!
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public interface IMenuContributor |
||||
|
{ |
||||
|
Task ConfigureMenuAsync(MenuConfigurationContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public interface IMenuManager |
||||
|
{ |
||||
|
Task<ApplicationMenu> GetAsync(string name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class MenuConfigurationContext : IMenuConfigurationContext |
||||
|
{ |
||||
|
public ApplicationMenu Menu { get; set; } |
||||
|
|
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
public MenuConfigurationContext(ApplicationMenu menu, IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
Menu = menu; |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class MenuManager : IMenuManager, ITransientDependency |
||||
|
{ |
||||
|
private readonly NavigationOptions _options; |
||||
|
private readonly IServiceProvider _serviceProvider; |
||||
|
|
||||
|
public MenuManager( |
||||
|
IOptions<NavigationOptions> options, |
||||
|
IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
_serviceProvider = serviceProvider; |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task<ApplicationMenu> GetAsync(string name) |
||||
|
{ |
||||
|
var menu = new ApplicationMenu(name); |
||||
|
|
||||
|
using (var scope = _serviceProvider.CreateScope()) |
||||
|
{ |
||||
|
var context = new MenuConfigurationContext(menu, scope.ServiceProvider); |
||||
|
|
||||
|
foreach (var contributor in _options.MenuContributors) |
||||
|
{ |
||||
|
await contributor.ConfigureMenuAsync(context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return menu; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class NavigationOptions |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public List<IMenuContributor> MenuContributors { get; } |
||||
|
|
||||
|
public NavigationOptions() |
||||
|
{ |
||||
|
MenuContributors = new List<IMenuContributor>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public static class StandardMenus |
||||
|
{ |
||||
|
public const string Main = "Main"; |
||||
|
public const string User = "User"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,102 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.TestBase; |
||||
|
using Volo.ExtensionMethods.Collections.Generic; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Ui.Navigation |
||||
|
{ |
||||
|
public class MenuManager_Tests : AbpIntegratedTest<MenuManager_Tests.TestModule> |
||||
|
{ |
||||
|
private readonly IMenuManager _menuManager; |
||||
|
|
||||
|
public MenuManager_Tests() |
||||
|
{ |
||||
|
_menuManager = ServiceProvider.GetRequiredService<IMenuManager>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Get_Menu() |
||||
|
{ |
||||
|
var mainMenu = await _menuManager.GetAsync(StandardMenus.Main); |
||||
|
|
||||
|
mainMenu.Name.ShouldBe(StandardMenus.Main); |
||||
|
mainMenu.DisplayName.ShouldBe("Main Menu"); |
||||
|
mainMenu.Items.Count.ShouldBe(2); |
||||
|
mainMenu.Items[0].Name.ShouldBe("Dashboard"); |
||||
|
mainMenu.Items[1].Name.ShouldBe("Administration"); |
||||
|
mainMenu.Items[1].Items[0].Name.ShouldBe("Administration.UserManagement"); |
||||
|
mainMenu.Items[1].Items[1].Name.ShouldBe("Administration.RoleManagement"); |
||||
|
mainMenu.Items[1].Items[2].Name.ShouldBe("Administration.DashboardSettings"); |
||||
|
} |
||||
|
|
||||
|
public class TestModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.Configure<NavigationOptions>(options => |
||||
|
{ |
||||
|
options.MenuContributors.Add(new TestMenuContributer1()); |
||||
|
options.MenuContributors.Add(new TestMenuContributer2()); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Adds menu items: |
||||
|
* - Administration |
||||
|
* - User Management |
||||
|
* - Role Management |
||||
|
*/ |
||||
|
public class TestMenuContributer1 : IMenuContributor |
||||
|
{ |
||||
|
public Task ConfigureMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Menu.Name != StandardMenus.Main) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
context.Menu.DisplayName = "Main Menu"; |
||||
|
|
||||
|
var administration = context.Menu.Items.GetOrAdd( |
||||
|
m => m.Name == "Administration", |
||||
|
() => new ApplicationMenuItem("Administration", "Administration") |
||||
|
); |
||||
|
|
||||
|
administration.AddItem(new ApplicationMenuItem("Administration.UserManagement", "User Management")); |
||||
|
administration.AddItem(new ApplicationMenuItem("Administration.RoleManagement", "Role Management")); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Adds menu items: |
||||
|
* - Dashboard |
||||
|
* - Administration |
||||
|
* - Dashboard Settings |
||||
|
*/ |
||||
|
public class TestMenuContributer2 : IMenuContributor |
||||
|
{ |
||||
|
public Task ConfigureMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Menu.Name != StandardMenus.Main) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
context.Menu.Items.Insert(0, new ApplicationMenuItem("Dashboard", "Dashboard")); |
||||
|
|
||||
|
var administration = context.Menu.Items.GetOrAdd( |
||||
|
m => m.Name == "Administration", |
||||
|
() => new ApplicationMenuItem("Administration", "Administration") |
||||
|
); |
||||
|
|
||||
|
administration.AddItem(new ApplicationMenuItem("Administration.DashboardSettings", "Dashboard Settings")); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue