Skip to content

Commit

Permalink
feat(WinBox): add ShowModal method (#4132)
Browse files Browse the repository at this point in the history
* feat: 增加 ShowModal 方法

* style: 更新样式名称

* feat: 增加级联参数

* feat: 增加关闭弹窗按钮

* chore: 增加字典

* style: 增加内置样式

* feat: 增加 Stack 方法

* feat: 增加最大化最小化恢复窗口方法

* doc: 更新示例

* feat: 增加 Overflow 参数

* style: 增加不换行样式

* feat: 增加设置标题图标方法

* doc: 更新文档

* doc: 更新示例增加功能按钮

* feat: 更正OnShow 回调

* refactor: 删除冗余变量

* doc: 增加 Modal 示例

* refactor: 增加 modal 样式

* test: 更新 DateTimePicker 单元测试

* test: 增加 Root 单元测试

* test: 更新 Button 单元测试

* Revert "test: 更新 DateTimePicker 单元测试"

This reverts commit b6a9875.

* Revert "test: 更新 Button 单元测试"

This reverts commit b82fe2a.

* chore: bump version 8.0.0-beta04

* chore: bump version 8.0.0-beta04
  • Loading branch information
ArgoZhang authored Aug 23, 2024
1 parent 7dc2eed commit 511a88e
Show file tree
Hide file tree
Showing 16 changed files with 441 additions and 60 deletions.
1 change: 1 addition & 0 deletions exclusion.dic
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ webp
Pdfi
simhei
Hmmss
winbox
2 changes: 1 addition & 1 deletion src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<PackageReference Include="BootstrapBlazor.Topology" Version="8.0.9" />
<PackageReference Include="BootstrapBlazor.VideoPlayer" Version="8.0.7-beta1" />
<PackageReference Include="BootstrapBlazor.WebAPI" Version="8.0.5" />
<PackageReference Include="BootstrapBlazor.WinBox" Version="8.0.0-beta03" />
<PackageReference Include="BootstrapBlazor.WinBox" Version="8.0.0-beta04" />
<PackageReference Include="Longbow.Logging" Version="8.0.0" />
<PackageReference Include="Longbow.Tasks" Version="8.0.3" />
<PackageReference Include="System.Drawing.Common" Version="8.0.8" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="bb-winbox-body">
<h3>Custom WinBox Content Create @DateTime.Now</h3>
</div>

<div class="bb-winbox-footer">
<Button Text="Stack" OnClickWithoutRender="StackWinBox"></Button>
<Button Text="Minimize" OnClickWithoutRender="MinWinBox"></Button>
<Button Text="Maximize" OnClickWithoutRender="MaxWinBox"></Button>
<Button Text="Restore" OnClickWithoutRender="RestoreWinBox"></Button>
<Button Text="SetTitle" OnClickWithoutRender="SetTitleWinBox"></Button>
<Button Text="SetIcon" OnClickWithoutRender="SetIconWinBox"></Button>
<WinBoxCloseButton />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Argo Zhang ([email protected]). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace BootstrapBlazor.Server.Components.Components;

/// <summary>
/// CustomWinBoxContent 组件
/// </summary>
public partial class CustomWinBoxContent
{
[Inject, NotNull]
private WinBoxService? WinBoxService { get; set; }

/// <summary>
/// WinBoxOption 实例
/// </summary>
[Parameter, NotNull]
public WinBoxOption? Option { get; set; }

private Task StackWinBox() => WinBoxService.Stack();

private async Task MinWinBox()
{
if (Option != null)
{
await WinBoxService.Minimize(Option);
}
}

private async Task MaxWinBox()
{
if (Option != null)
{
await WinBoxService.Maximize(Option);
}
}

private async Task RestoreWinBox()
{
if (Option != null)
{
await WinBoxService.Restore(Option);
}
}

private async Task SetIconWinBox()
{
if (Option != null)
{
Option.Icon = "./images/Argo-C.png";
await WinBoxService.SetIcon(Option);
}
}

private async Task SetTitleWinBox()
{
if (Option != null)
{
Option.Title = $"{DateTime.Now}";
await WinBoxService.SetTitle(Option);
}
}
}
69 changes: 61 additions & 8 deletions src/BootstrapBlazor.Server/Components/Samples/WinBoxes.razor
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,89 @@ private WinBoxService? WinBoxService { get; set; }</Pre>
<DemoBlock Title="@Localizer["WinBoxNormalTitle"]"
Introduction="@Localizer["WinBoxNormalIntro"]"
Name="Normal">
<Button Text="Run" OnClickWithoutRender="OpenWinBox"></Button>
<Button Text="Show" OnClickWithoutRender="() => OpenWinBox(null)"></Button>
<Button Text="Modal" OnClickWithoutRender="OpenModalWinBox"></Button>
<ConsoleLogger @ref="_logger"></ConsoleLogger>
</DemoBlock>

<p class="code-label mt-3">常见问题</p>

<GroupBox Title="更改标题背景色" class="mb-3">
<p>通过 <code>WinBoxOption</code> 参数 <code>Background</code> 设置</p>
<p class="code-label">通过 <code>WinBoxOption</code> 参数 <code>Background</code> 设置</p>
<Pre>new WinBoxOption() { Background = "#000" }</Pre>

<p>通过 <code>WinBoxOption</code> 参数 <code>Class</code> 设置</p>
<p class="code-label">通过 <code>WinBoxOption</code> 参数 <code>Class</code> 设置</p>
<Pre>new WinBoxOption() { Class = ".bb-win-box" }</Pre>
<Pre>.bb-win-box {
background: #000;
}</Pre>

<p>通过样式变量实现</p>
<p class="code-label">通过样式变量实现</p>
<Pre>.winbox {
--bb-winbox-bg: var(--bb-primary-color) !important;
--bb-winbox-bg: var(--bb-primary-color);
}</Pre>
</GroupBox>

<GroupBox Title="更改边框" class="mb-3">
<p>通过 <code>WinBoxOption</code> 参数 <code>Border</code> 设置</p>
<p class="code-label">通过 <code>WinBoxOption</code> 参数 <code>Border</code> 设置</p>
<Pre>new WinBoxOption() { Border = 3 }</Pre>
</GroupBox>

<GroupBox Title="设置图标" class="mb-3">
<p class="code-label">通过 <code>WinBoxOption</code> 参数 <code>Icon</code> 设置</p>
<Pre>new WinBoxOption() { Icon = "./images/Argo-C.png" }</Pre>

<p class="code-label">通过服务方法 <code>WinBoxService</code> 实例方法</p>
<Pre>[Inject]
[NotNull]
private WinBoxService? WinBoxService { get; set; }

private async Task SetIcon()
{
// 提前保持弹窗 WinBoxOption 实例
option.Icon = "./images/Argo-C.png";
await WinBoxService.setIcon(option.Id);
}</Pre>
</GroupBox>

<GroupBox Title="模式弹窗" class="mb-3">
<p>通过 <code>WinBoxOption</code> 参数 <code>Modal</code> 设置</p>
<p class="code-label">通过 <code>WinBoxOption</code> 参数 <code>Modal</code> 设置</p>
<Pre>new WinBoxOption() { Modal = true }</Pre>

<p class="code-label">通过扩展方法 <code>WinBoxService.ShowModal</code></p>
<Pre>WinBoxService.ShowModal&lt;Count&gt;("Title")</Pre>
</GroupBox>

<GroupBox Title="代码关闭弹窗" class="mb-3">
<p class="code-label">通过 <code>WinBoxCloseButton</code> 组件</p>
<Pre>&lt;WinBoxCloseButton /&gt;</Pre>

<p class="code-label">通过服务方法 <code>WinBoxService</code> 实例方法</p>

<p class="code-label">弹窗内: 使用级联参数 <code>OnCloseAsync</code> <code>WinBoxOption</code> 关闭弹窗</p>
<Pre>[CascadingParameter]
private Func&lt;WinBoxOption, Task&gt;? OnCloseAsync { get; set; }

[CascadingParameter]
private WinBoxOption? Option { get; set; }

private async Task Close()
{
if (OnCloseAsync != null && Option != null)
{
await OnCloseAsync(Option);
}
}</Pre>

<p class="code-label">弹窗外: 使用 <code>WinBoxService</code> 服务实例方法 <code>CloseAsync</code> 关闭弹窗</p>
<Pre>[Inject]
[NotNull]
private WinBoxService? WinBoxService { get; set; }

private async Task Close()
{
// 提前保持弹窗 WinBoxOption 实例
await WinBoxService.CloseAsync(option.Id);
}</Pre>
</GroupBox>

<p>更多参数信息可参考 <a href="https:/dotnetcore/BootstrapBlazor/blob/main/src/Extensions/Components/BootstrapBlazor.WinBox/WinBoxOption.cs" target="_blank">WinBoxOption</a> 注释</p>
Expand Down
16 changes: 13 additions & 3 deletions src/BootstrapBlazor.Server/Components/Samples/WinBoxes.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,16 @@ public partial class WinBoxes
Background = "var(--bb-primary-color)"
};

private async Task OpenWinBox()
private Task OpenModalWinBox()
{
var option = DefaultOptions;
option.Modal = true;
return OpenWinBox(option);
}

private async Task OpenWinBox(WinBoxOption? option)
{
option ??= DefaultOptions;
option.OnCloseAsync = () =>
{
_logger.Log($"WinBoxOption({option.Id}) Trigger OnCloseAsync");
Expand All @@ -35,7 +42,7 @@ private async Task OpenWinBox()
_logger.Log($"WinBoxOption({option.Id}) Trigger OnCreateAsync");
return Task.CompletedTask;
};
option.OnShownAsync = () =>
option.OnShowAsync = () =>
{
_logger.Log($"WinBoxOption({option.Id}) Trigger OnShownAsync");
return Task.CompletedTask;
Expand Down Expand Up @@ -75,7 +82,10 @@ private async Task OpenWinBox()
_logger.Log($"WinBoxOption({option.Id}) Trigger OnMinimizeAsync");
return Task.CompletedTask;
};
await WinBoxService.Show<Counter>("Test", option: option);

await WinBoxService.Show<CustomWinBoxContent>("Test", new Dictionary<string, object?>() {
{ "Option", option }
}, option);
}

private AttributeItem[] GetAttributes() =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>8.0.0-beta03</Version>
<Version>8.0.0-beta04</Version>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,31 @@ public static async Task Show(this WinBoxService service, string title, Type typ
option.ContentTemplate = BootstrapDynamicComponent.CreateComponent(type, parameters).Render();
await service.Show(option);
}

/// <summary>
/// <see cref="WinBoxService"/> 扩展方法
/// </summary>
/// <typeparam name="TComponent">内容组件</typeparam>
/// <param name="service"><see cref="WinBoxService"/> 实例</param>
/// <param name="title">指定窗口标题</param>
/// <param name="parameters">指定组件参数集合</param>
/// <param name="option">额外参数集合</param>
public static Task ShowModal<TComponent>(this WinBoxService service, string title, IDictionary<string, object?>? parameters = null, WinBoxOption? option = null) where TComponent : ComponentBase => ShowModal(service, title, typeof(TComponent), parameters, option);

/// <summary>
/// <see cref="WinBoxService"/> 扩展方法
/// </summary>
/// <param name="service"><see cref="WinBoxService"/> 实例</param>
/// <param name="title">指定窗口标题</param>
/// <param name="type">指定内容组件类型</param>
/// <param name="parameters">指定组件参数集合</param>
/// <param name="option">额外参数集合</param>
public static async Task ShowModal(this WinBoxService service, string title, Type type, IDictionary<string, object?>? parameters = null, WinBoxOption? option = null)
{
option ??= new WinBoxOption();
option.Title = title;
option.Modal = true;
option.ContentTemplate = BootstrapDynamicComponent.CreateComponent(type, parameters).Render();
await service.Show(option);
}
}
20 changes: 12 additions & 8 deletions src/Extensions/Components/BootstrapBlazor.WinBox/WinBox.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
@inherits BootstrapModuleComponentBase
@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.WinBox/WinBox.razor.js", JSObjectReference = true)]

@foreach (var item in _cache.Values)
{
<template @key="item" id="@item.Id">
<div class="bb-win-box-content">
@item?.ContentTemplate
</div>
</template>
}
<CascadingValue Value="CloseAsync" IsFixed="true">
@foreach (var (key, item) in _cache)
{
<template @key="key" id="@item?.Id">
<CascadingValue Value="item" IsFixed="true">
<div class="bb-winbox-content">
@item?.ContentTemplate
</div>
</CascadingValue>
</template>
}
</CascadingValue>
40 changes: 36 additions & 4 deletions src/Extensions/Components/BootstrapBlazor.WinBox/WinBox.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected override void OnInitialized()
base.OnInitialized();

// 注册 Dialog 弹窗事件
WinBoxService.Register(this, Show);
WinBoxService.Register(this, Execute);
}

/// <summary>
Expand All @@ -50,6 +50,33 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
}
}

private async Task Execute(WinBoxOption? option, string method)
{
if (method == "stack")
{
await InvokeVoidAsync("stack");
}
else if (option != null)
{
if (method == "show")
{
await Show(option);
}
else if (method == "setIcon")
{
await InvokeVoidAsync("execute", option.Id, method, option.Icon);
}
else if (method == "setTitle")
{
await InvokeVoidAsync("execute", option.Id, method, option.Title);
}
else
{
await InvokeVoidAsync("execute", option.Id, method);
}
}
}

private bool _render;
private async Task Show(WinBoxOption option)
{
Expand All @@ -69,6 +96,11 @@ private async Task Show(WinBoxOption option)
}
}

private async Task CloseAsync(WinBoxOption option)
{
await InvokeVoidAsync("execute", option.Id, "close");
}

/// <summary>
/// 弹窗关闭回调方法由 JavaScript 调用
/// </summary>
Expand Down Expand Up @@ -103,11 +135,11 @@ public async Task OnCreate(string id)
/// <param name="id"></param>
/// <returns></returns>
[JSInvokable]
public async Task OnShown(string id)
public async Task OnShow(string id)
{
if (_cache.TryGetValue(id, out var option) && option.OnShownAsync != null)
if (_cache.TryGetValue(id, out var option) && option.OnShowAsync != null)
{
await option.OnShownAsync();
await option.OnShowAsync();
}
}

Expand Down
Loading

0 comments on commit 511a88e

Please sign in to comment.