Browse Source

Resolved #1361: Layout Hook Feature for MVC UI

pull/1363/head
Halil İbrahim Kalkan 7 years ago
parent
commit
63bc860d75
  1. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml
  2. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
  3. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml
  4. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
  5. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs
  6. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml
  7. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs
  8. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookOptions.cs
  9. 27
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs
  10. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs
  11. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs
  12. 24
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/ViewComponentHelperLayoutHookExtensions.cs

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml

@ -2,11 +2,13 @@
@using Microsoft.Extensions.Options
@using Volo.Abp.AspNetCore.MultiTenancy
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.MainNavbar
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Abp.MultiTenancy
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@ -25,6 +27,8 @@
<html lang="en">
<head>
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Account)
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
@ -34,16 +38,19 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@await RenderSectionAsync("styles", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Account)
</head>
<body class="abp-account-layout">
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Account)
@(await Component.InvokeAsync<MainNavbarViewComponent>())
<div class="@containerClass">
<abp-row>
<abp-column size-md="_4" offset-md="_4">
@if (MultiTenancyOptions.Value.IsEnabled &&
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
@if (MultiTenancyOptions.Value.IsEnabled &&
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
{
<div class="tenant-switch-box" style="background-color: #eee; margin-bottom: 20px; color: #000; padding: 10px; text-align: center;">
<span style="color: #666;">@MultiTenancyStringLocalizer["Tenant"]: </span>
@ -73,5 +80,6 @@
@await RenderSectionAsync("scripts", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Account)
</body>
</html>

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml

@ -1,9 +1,11 @@
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.MainNavbar
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@ -29,6 +31,8 @@
<html lang="en">
<head>
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Application)
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
@ -38,8 +42,11 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@await RenderSectionAsync("styles", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Application)
</head>
<body class="abp-application-layout">
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application)
@(await Component.InvokeAsync<MainNavbarViewComponent>())
@ -58,5 +65,6 @@
@await RenderSectionAsync("scripts", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application)
</body>
</html>

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml

@ -1,8 +1,10 @@
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@ -28,6 +30,8 @@
<html lang="en">
<head>
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Empty)
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
@ -37,8 +41,11 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@await RenderSectionAsync("styles", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Empty)
</head>
<body class="abp-empty-layout">
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Empty)
<div class="@containerClass">
@(await Component.InvokeAsync<PageAlertsViewComponent>())
@ -52,5 +59,6 @@
@await RenderSectionAsync("scripts", false)
@await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Empty)
</body>
</html>

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj

@ -10,6 +10,11 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\**\*.cshtml" />
<Content Remove="Volo\**\*.cshtml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUglify" Version="1.5.13" />
</ItemGroup>

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs

@ -1,5 +1,6 @@
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI
{
@ -7,6 +8,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI
[DependsOn(typeof(AbpUiNavigationModule))]
public class AbpAspNetCoreMvcUiModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiModule>();
});
}
}
}

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml

@ -0,0 +1,9 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@model LayoutHookViewModel
@if (Model.Hooks.Any())
{
foreach (var hook in Model.Hooks)
{
<text>@await Component.InvokeAsync(hook.ComponentType, new { layout = Model.Layout })</text>
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs

@ -0,0 +1,24 @@
using System;
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public class LayoutHookInfo
{
/// <summary>
/// ViewComponent type.
/// </summary>
public Type ComponentType { get; }
/// <summary>
/// Specifies the layout name to apply this hook.
/// null indicates that this hook will be applied to all layouts.
/// </summary>
public string Layout { get; }
public LayoutHookInfo(Type componentType, string layout = null)
{
ComponentType = componentType;
Layout = layout;
}
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookOptions.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public class LayoutHookOptions
{
public IDictionary<string, List<LayoutHookInfo>> Hooks { get; }
public LayoutHookOptions()
{
Hooks = new Dictionary<string, List<LayoutHookInfo>>();
}
public LayoutHookOptions Add(string name, Type componentType, string layout = null)
{
Hooks
.GetOrAdd(name, () => new List<LayoutHookInfo>())
.Add(new LayoutHookInfo(componentType, layout));
return this;
}
}
}

27
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public class LayoutHookViewComponent : AbpViewComponent
{
protected LayoutHookOptions Options { get; }
public LayoutHookViewComponent(IOptions<LayoutHookOptions> options)
{
Options = options.Value;
}
public virtual IViewComponentResult Invoke(string name, string layout)
{
var hooks = Options.Hooks.GetOrDefault(name)?.ToArray() ?? Array.Empty<LayoutHookInfo>();
return View(
"~/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml",
new LayoutHookViewModel(hooks, layout)
);
}
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public class LayoutHookViewModel
{
public LayoutHookInfo[] Hooks { get; }
public string Layout { get; }
public LayoutHookViewModel(LayoutHookInfo[] hooks, string layout)
{
Hooks = hooks;
Layout = layout;
}
}
}

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public static class LayoutHooks
{
public static class Head
{
public const string First = "Header.First";
public const string Last = "Header.Last";
}
public static class Body
{
public const string First = "Body.First";
public const string Last = "Body.Last";
}
}
}

24
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/ViewComponentHelperLayoutHookExtensions.cs

@ -0,0 +1,24 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
{
public static class ViewComponentHelperLayoutHookExtensions
{
public static Task<IHtmlContent> InvokeLayoutHookAsync(
this IViewComponentHelper componentHelper,
string name,
string layout)
{
return componentHelper.InvokeAsync(
typeof(LayoutHookViewComponent),
new
{
name = name,
layout = layout
}
);
}
}
}
Loading…
Cancel
Save