From 84a3b742c244ac4d3ecceec1b508193780e95bc5 Mon Sep 17 00:00:00 2001 From: zxyao Date: Sat, 22 Aug 2020 09:24:55 +0800 Subject: [PATCH] feat(module: modal): support getting the result from confirm (#476) * feat(module: confirm): support blocking to get the result of confirm * refactor: change modalservice Confirm return value,add ConfirmAsync FUNC * feat: add ConfirmService * fix: button text Co-authored-by: ElderJames --- AntDesign.sln | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 1 + components/modal/ComfirmContainer.razor.cs | 9 + components/modal/ConfirmDialog.razor | 159 ++++++++--- components/modal/ConfirmDialog.razor.cs | 76 +++-- components/modal/ConfirmService.cs | 71 +++++ components/modal/ModalFooter.razor | 4 +- components/modal/ModalRef.cs | 3 + components/modal/ModalService.cs | 120 +++++--- components/modal/config/ButtonProps.cs | 15 +- .../modal/config/ConfirmButtonOptions.cs | 29 ++ components/modal/config/ConfirmOptions.cs | 263 ++++++++++++++++-- components/modal/type/ConfirmButtons.cs | 51 ++++ components/modal/type/ConfirmIcon.cs | 66 +++++ components/modal/type/ConfirmResult.cs | 23 ++ components/popconfirm/Popconfirm.razor | 4 +- .../Demos/Components/Modal/demo/Confirm.razor | 25 +- .../Modal/demo/ConfirmPromise.razor | 8 +- .../Components/Modal/demo/ConfirmRouter.razor | 3 +- .../Modal/demo/Confirm_Service.razor | 81 ++++++ .../Demos/Components/Modal/demo/Info.razor | 12 +- .../Demos/Components/Modal/demo/Locale.razor | 4 +- .../Demos/Components/Modal/demo/Manual.razor | 2 +- .../Demos/Components/Modal/demo/confirm.md | 71 ----- .../Components/Modal/demo/confirm_service.md | 14 + .../Demos/Components/Modal/doc/index.en-US.md | 6 + .../Demos/Components/Modal/doc/index.zh-CN.md | 6 + 27 files changed, 905 insertions(+), 223 deletions(-) create mode 100644 components/modal/ConfirmService.cs create mode 100644 components/modal/config/ConfirmButtonOptions.cs create mode 100644 components/modal/type/ConfirmButtons.cs create mode 100644 components/modal/type/ConfirmIcon.cs create mode 100644 components/modal/type/ConfirmResult.cs create mode 100644 site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm_Service.razor create mode 100644 site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm_service.md diff --git a/AntDesign.sln b/AntDesign.sln index 3429653b..4ca285dd 100644 --- a/AntDesign.sln +++ b/AntDesign.sln @@ -29,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntDesign.Docs.Build.CLI", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "hosts", "hosts", "{752F5AE8-BA08-4C41-B9B2-D2ED12727E63}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntDesign.Tests", "tests\AntDesign.Tests.csproj", "{B2DC89BD-838C-459C-A32A-98F877479988}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AntDesign.Tests", "tests\AntDesign.Tests.csproj", "{B2DC89BD-838C-459C-A32A-98F877479988}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/components/core/Extensions/ServiceCollectionExtensions.cs b/components/core/Extensions/ServiceCollectionExtensions.cs index e61e2a18..51625771 100644 --- a/components/core/Extensions/ServiceCollectionExtensions.cs +++ b/components/core/Extensions/ServiceCollectionExtensions.cs @@ -24,6 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); + services.TryAddScoped(); return services; } diff --git a/components/modal/ComfirmContainer.razor.cs b/components/modal/ComfirmContainer.razor.cs index 4513e239..7ab0bf72 100644 --- a/components/modal/ComfirmContainer.razor.cs +++ b/components/modal/ComfirmContainer.razor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; @@ -12,6 +13,9 @@ namespace AntDesign [Inject] private ModalService ModalService { get; set; } + [Inject] + private ConfirmService ConfirmService { get; set; } + private List _modalRefs = new List(); protected override void OnInitialized() @@ -21,6 +25,8 @@ namespace AntDesign ModalService.OnDestroyEvent += Modal_OnDestroy; ModalService.OnDestroyAllEvent += Modal_OnDestroyAll; ModalService.OnUpdateEvent += Modal_OnUpdate; + + ConfirmService.OnOpenEvent += Modal_OnOpen; } /// @@ -31,6 +37,7 @@ namespace AntDesign modalRef.Config.Visible = true; if (!_modalRefs.Contains(modalRef)) { + modalRef.Config.BuildButtonsDefaultOptions(); _modalRefs.Add(modalRef); } await InvokeAsync(StateHasChanged); @@ -92,6 +99,8 @@ namespace AntDesign ModalService.OnDestroyAllEvent -= Modal_OnDestroyAll; ModalService.OnUpdateEvent -= Modal_OnUpdate; + ConfirmService.OnOpenEvent -= Modal_OnOpen; + base.Dispose(disposing); } } diff --git a/components/modal/ConfirmDialog.razor b/components/modal/ConfirmDialog.razor index 6e78756b..3ce15d34 100644 --- a/components/modal/ConfirmDialog.razor +++ b/components/modal/ConfirmDialog.razor @@ -1,6 +1,6 @@ @namespace AntDesign @inherits AntDomComponentBase - +@using OneOf;
@@ -9,7 +9,7 @@ { @(Config.Icon) } - + @if(Config.Title != null) { var titleValue = Config.Title.Value; @@ -38,59 +38,132 @@
@{ - var cancelProps = Config.CancelButtonProps; - var okProps = Config.OkButtonProps; - } - @if (Config.OkCancel) - { - - + ); + btnRef = innerBtnRef; + return compontent; + } } - + case ConfirmButtons.YesNo: + { + @BuildButton(Config.Button1Props, async (e) => + { + await HandleBtn1Click(e, ConfirmResult.Yes); + }, out _okBtn); + + @BuildButton(Config.Button2Props, async (e) => + { + await HandleBtn2Click(e, ConfirmResult.No); + }, out _cancelBtn); + + break; + } + case ConfirmButtons.YesNoCancel: + { + @BuildButton(Config.Button1Props, async (e) => + { + await HandleBtn1Click(e, ConfirmResult.Yes); + }, out _okBtn); + + @BuildButton(Config.Button2Props, async (e) => + { + await HandleBtn2Click(e, ConfirmResult.No); + }, out _cancelBtn); + + @BuildButton(Config.Button3Props, async (e) => + { + await HandleBtn3Click(e, ConfirmResult.Cancel); + }, out _); + break; + } + + case ConfirmButtons.RetryCancel: + { + @BuildButton(Config.Button1Props, async (e) => + { + await HandleBtn1Click(e, ConfirmResult.Retry); + }, out _okBtn); + + @BuildButton(Config.Button2Props, async (e) => + { + await HandleBtn2Click(e, ConfirmResult.Cancel); + }, out _cancelBtn); + + break; + } + case ConfirmButtons.AbortRetryIgnore: + { + @BuildButton(Config.Button1Props, async (e) => + { + await HandleBtn1Click(e, ConfirmResult.Abort); + }, out _okBtn); + + @BuildButton(Config.Button2Props, async (e) => + { + await HandleBtn2Click(e, ConfirmResult.Retry); + }, out _cancelBtn); + + @BuildButton(Config.Button3Props, async (e) => + { + await HandleBtn3Click(e, ConfirmResult.Ignore); + }, out _); + + break; + } + }
\ No newline at end of file diff --git a/components/modal/ConfirmDialog.razor.cs b/components/modal/ConfirmDialog.razor.cs index 95e9a1cf..e79257bd 100644 --- a/components/modal/ConfirmDialog.razor.cs +++ b/components/modal/ConfirmDialog.razor.cs @@ -63,7 +63,7 @@ namespace AntDesign config.Title = null; config.CloseIcon = null; config.OnClosed = Close; - config.OnCancel = HandleCancel; + config.OnCancel = ModalRef.IsCreateByModalService ? HandleCancel : new Func(async (e) => await Close()); return config; } @@ -74,7 +74,10 @@ namespace AntDesign var element = Config.AutoFocusButton == ConfirmAutoFocusButton.Cancel ? _cancelBtn : _okBtn; - await JsInvokeAsync(JSInteropConstants.focusDialog, $"#{element.Id}"); + if (element != null) + { + await JsInvokeAsync(JSInteropConstants.focusDialog, $"#{element.Id}"); + } } await base.OnAfterRenderAsync(firstRender); @@ -90,24 +93,21 @@ namespace AntDesign } } - private async Task HandleOk(MouseEventArgs e) { var args = new ModalClosingEventArgs(e, false); if (ModalRef.ModalTemplate != null) await ModalRef.ModalTemplate.OkAsync(args); - if (args.Cancel == false) + + if (!args.Cancel && Config.OnOk != null) { - if (Config.OnOk != null) - { - Config.OkButtonProps.Loading = true; - await InvokeAsync(StateHasChanged); - await Config.OnOk.Invoke(args); - } + Config.OkButtonProps.Loading = true; + await InvokeAsync(StateHasChanged); + await Config.OnOk.Invoke(args); } - if (args.Cancel == true) + if (args.Cancel) { Config.OkButtonProps.Loading = false; await InvokeAsync(StateHasChanged); @@ -115,26 +115,25 @@ namespace AntDesign else { await Close(); + ModalRef.TaskCompletionSource?.SetResult(ConfirmResult.OK); } } private async Task HandleCancel(MouseEventArgs e) { + var args = new ModalClosingEventArgs(e, false); if (ModalRef.ModalTemplate != null) await ModalRef.ModalTemplate.CancelAsync(args); - if (args.Cancel == false) + if (!args.Cancel && Config.OnCancel != null) { - if (Config.OnCancel != null) - { - Config.CancelButtonProps.Loading = true; - await InvokeAsync(StateHasChanged); - await Config.OnCancel.Invoke(args); - } + Config.CancelButtonProps.Loading = true; + await InvokeAsync(StateHasChanged); + await Config.OnCancel.Invoke(args); } - if (args.Cancel == true) + if (args.Cancel) { Config.CancelButtonProps.Loading = false; await InvokeAsync(StateHasChanged); @@ -142,7 +141,46 @@ namespace AntDesign else { await Close(); + ModalRef.TaskCompletionSource?.SetResult(ConfirmResult.Cancel); } } + + private async Task HandleBtn1Click(MouseEventArgs e, ConfirmResult confirmResult) + { + if (ModalRef.IsCreateByModalService) + { + await HandleOk(e); + } + else + { + Config.Button1Props.Loading = false; + await InvokeAsync(StateHasChanged); + await Close(); + ModalRef.TaskCompletionSource?.SetResult(confirmResult); + } + } + + private async Task HandleBtn2Click(MouseEventArgs e, ConfirmResult confirmResult) + { + if (ModalRef.IsCreateByModalService) + { + await HandleCancel(e); + } + else + { + Config.Button2Props.Loading = false; + await InvokeAsync(StateHasChanged); + await Close(); + ModalRef.TaskCompletionSource?.SetResult(confirmResult); + } + } + + private async Task HandleBtn3Click(MouseEventArgs e, ConfirmResult confirmResult) + { + Config.Button3Props.Loading = false; + await InvokeAsync(StateHasChanged); + await Close(); + ModalRef.TaskCompletionSource?.SetResult(confirmResult); + } } } diff --git a/components/modal/ConfirmService.cs b/components/modal/ConfirmService.cs new file mode 100644 index 00000000..08bf66e2 --- /dev/null +++ b/components/modal/ConfirmService.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using OneOf; + +namespace AntDesign +{ + public class ConfirmService + { + internal event Func OnOpenEvent; + + /// + /// + /// + /// + /// + /// + /// + /// + /// + public async Task Show( + OneOf content, + OneOf title, + ConfirmButtons confirmButtons, + ConfirmIcon confirmIcon, + ConfirmButtonOptions options) + { + if (options == null) throw new ArgumentNullException(nameof(options)); + ConfirmOptions confirmOptions = new ConfirmOptions() + { + Title = title, + Content = content, + ConfirmButtons = confirmButtons, + ConfirmIcon = confirmIcon, + }; + + #region config button default properties + + if (options.Button1Props != null) + { + confirmOptions.Button1Props = options.Button1Props; + } + if (options.Button2Props != null) + { + confirmOptions.Button2Props = options.Button2Props; + } + if (options.Button3Props != null) + { + confirmOptions.Button3Props = options.Button3Props; + } + + #endregion + + var modalRef = new ModalRef(confirmOptions); + modalRef.TaskCompletionSource = new TaskCompletionSource(); ; + await OnOpenEvent?.Invoke(modalRef); + return await modalRef.TaskCompletionSource.Task; + } + + public Task Show + (OneOf content, + OneOf title, + ConfirmButtons confirmButtons = ConfirmButtons.OKCancel, + ConfirmIcon confirmIcon = ConfirmIcon.Info) + { + return Show(content, title, confirmButtons, confirmIcon, new ConfirmButtonOptions()); + } + } +} diff --git a/components/modal/ModalFooter.razor b/components/modal/ModalFooter.razor index 1665e132..beb7bc7f 100644 --- a/components/modal/ModalFooter.razor +++ b/components/modal/ModalFooter.razor @@ -20,7 +20,7 @@ Size="@cancelProps.Size" Icon="@cancelProps.Icon" Disabled="@cancelProps.Disabled" - Danger="@cancelProps.Danger" + Danger="@cancelProps.IsDanger" > @{ if (ModalProps.CancelText.IsT0) @@ -46,7 +46,7 @@ Size="@okProps.Size" Icon="@okProps.Icon" Disabled="@okProps.Disabled" - Danger="@okProps.Danger" + Danger="@okProps.IsDanger" > @{ if (ModalProps.OkText.IsT0) diff --git a/components/modal/ModalRef.cs b/components/modal/ModalRef.cs index 689d8f97..2a2aa79e 100644 --- a/components/modal/ModalRef.cs +++ b/components/modal/ModalRef.cs @@ -52,6 +52,8 @@ namespace AntDesign public Func OnDestroy { get; set; } + internal bool IsCreateByModalService => _service != null; + internal ModalRef(ConfirmOptions config) { Config = config; @@ -92,5 +94,6 @@ namespace AntDesign await _service?.Update(this); } + internal TaskCompletionSource TaskCompletionSource { get; set; } } } diff --git a/components/modal/ModalService.cs b/components/modal/ModalService.cs index 9afaa1b9..8df73c02 100644 --- a/components/modal/ModalService.cs +++ b/components/modal/ModalService.cs @@ -16,83 +16,113 @@ namespace AntDesign #region SimpleConfirm - public async Task Confirm(ConfirmOptions props) + public ModalRef Confirm(ConfirmOptions props) { ModalRef modalRef = new ModalRef(props, this); - await OnOpenEvent?.Invoke(modalRef); + modalRef.TaskCompletionSource = new TaskCompletionSource(); + OnOpenEvent?.Invoke(modalRef); return modalRef; } - public async Task Info(ConfirmOptions options) + public ModalRef Info(ConfirmOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } - options.Icon = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, "Type", "info-circle"); - builder.AddAttribute(2, "Theme", "outline"); - builder.CloseComponent(); - }; + options.ConfirmIcon = ConfirmIcon.Info; options.OkCancel = false; - options.ConfirmType = "info"; - return await Confirm(options); + return Confirm(options); } - public async Task Success(ConfirmOptions options) + public ModalRef Success(ConfirmOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } - options.Icon = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, "Type", "check-circle"); - builder.AddAttribute(2, "Theme", "outline"); - builder.CloseComponent(); - }; + options.ConfirmIcon = ConfirmIcon.Success; options.OkCancel = false; - options.ConfirmType = "success"; - return await Confirm(options); + return Confirm(options); } - public async Task Error(ConfirmOptions options) + public ModalRef Error(ConfirmOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } - options.Icon = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, "Type", "close-circle"); - builder.AddAttribute(2, "Theme", "outline"); - builder.CloseComponent(); - }; + options.ConfirmIcon = ConfirmIcon.Error; options.OkCancel = false; - options.ConfirmType = "error"; - return await Confirm(options); + return Confirm(options); } - public async Task Warning(ConfirmOptions options) + public ModalRef Warning(ConfirmOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } - options.Icon = (builder) => - { - builder.OpenComponent(0); - builder.AddAttribute(1, "Type", "exclamation-circle"); - builder.AddAttribute(2, "Theme", "outline"); - builder.CloseComponent(); - }; + options.ConfirmIcon = ConfirmIcon.Warning; options.OkCancel = false; - options.ConfirmType = "warning"; - return await Confirm(options); + return Confirm(options); + } + + public async Task ConfirmAsync(ConfirmOptions props) + { + ModalRef modalRef = new ModalRef(props, this); + modalRef.TaskCompletionSource = new TaskCompletionSource(); + await OnOpenEvent?.Invoke(modalRef); + + return await modalRef.TaskCompletionSource.Task + .ContinueWith(t => + { + return t.Result == ConfirmResult.OK; + }, TaskScheduler.Default); + } + + public Task InfoAsync(ConfirmOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + options.ConfirmIcon = ConfirmIcon.Info; + options.OkCancel = false; + return ConfirmAsync(options); + } + + public Task SuccessAsync(ConfirmOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + options.ConfirmIcon = ConfirmIcon.Success; + options.OkCancel = false; + return ConfirmAsync(options); + } + + public Task ErrorAsync(ConfirmOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + options.ConfirmIcon = ConfirmIcon.Error; + options.OkCancel = false; + return ConfirmAsync(options); + } + + public Task WarningAsync(ConfirmOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + options.ConfirmIcon = ConfirmIcon.Warning; + options.OkCancel = false; + return ConfirmAsync(options); } #endregion @@ -123,7 +153,7 @@ namespace AntDesign { CheckIsNull(config); ModalRef modalRef = new ModalRef(config, this); - await OnOpenEvent.Invoke(modalRef); + OnOpenEvent.Invoke(modalRef); return modalRef; } @@ -141,7 +171,7 @@ namespace AntDesign CheckIsNull(config); ModalRef modalRef = new ModalRef(config, this); - await OnOpenEvent.Invoke(modalRef); + OnOpenEvent.Invoke(modalRef); RenderFragment child = (builder) => { @@ -159,7 +189,7 @@ namespace AntDesign { if (OnOpenEvent != null) { - return OnOpenEvent.Invoke(modalRef); + OnOpenEvent.Invoke(modalRef); } return Task.CompletedTask; } diff --git a/components/modal/config/ButtonProps.cs b/components/modal/config/ButtonProps.cs index 6b64bd7b..2b53529f 100644 --- a/components/modal/config/ButtonProps.cs +++ b/components/modal/config/ButtonProps.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; +using OneOf; namespace AntDesign { @@ -26,6 +27,18 @@ namespace AntDesign public bool Disabled { get; set; } - public bool Danger { get; set; } + private bool? _danger; + public bool? Danger { get => _danger; set => _danger = value; } + + internal bool IsDanger + { + get + { + if (Danger.HasValue) return Danger.Value; + return false; + } + } + + public OneOf ChildContent { get; set; } = ""; } } diff --git a/components/modal/config/ConfirmButtonOptions.cs b/components/modal/config/ConfirmButtonOptions.cs new file mode 100644 index 00000000..f56e439d --- /dev/null +++ b/components/modal/config/ConfirmButtonOptions.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.AspNetCore.Components; +using OneOf; + +namespace AntDesign +{ + /// + /// config the confirm button's properties + /// + public class ConfirmButtonOptions + { + /// + /// the leftmost button properties in LTR layout + /// + public ButtonProps Button1Props { get; set; } + + /// + /// the secondary button properties in LTR layout + /// + public ButtonProps Button2Props { get; set; } + + /// + /// the third button properties in LTR layout + /// + public ButtonProps Button3Props { get; set; } + } +} diff --git a/components/modal/config/ConfirmOptions.cs b/components/modal/config/ConfirmOptions.cs index 07c58b04..bc0fdccf 100644 --- a/components/modal/config/ConfirmOptions.cs +++ b/components/modal/config/ConfirmOptions.cs @@ -10,6 +10,20 @@ namespace AntDesign { public class ConfirmOptions { + /// + /// OK + /// + internal static string DefaultBtn1Text = "OK"; + /// + /// Cancel + /// + internal static string DefaultBtn2Text = "Cancel"; + /// + /// Ignore + /// + internal static string DefaultBtn3Text = "Ignore"; + + public string ClassName { get; set; } public bool Visible { get; set; } @@ -18,51 +32,256 @@ namespace AntDesign public OneOf Content { get; set; } - public Func OnCancel { get; set; } - - public Func OnOk { get; set; } - - public ButtonProps OkButtonProps { get; set; } = new ButtonProps(){ Type = ButtonType.Primary}; - - public ButtonProps CancelButtonProps { get; set; } = new ButtonProps(); - public OneOf Width { get; set; } = 520; public bool Centered { get; set; } public bool Mask { get; set; } = true; - + public bool MaskClosable { get; set; } = false; public string MaskStyle { get; set; } - public OneOf OkText { get; set; } = "OK"; - - public string OkType { get; set; } = ButtonType.Primary; - - public OneOf CancelText { get; set; } = "Cancel"; - public RenderFragment? Icon { get; set; } = null; public int ZIndex { get; set; } = 1000; - /// - /// 显示Cancel按钮 - /// - public bool OkCancel { get; set; } = true; - public string Style { get; set; } public bool Keyboard { get; set; } = true; - public ConfirmAutoFocusButton AutoFocusButton { get; set; } - public string TransitionName { get; set; } public string MaskTransitionName { get; set; } public ElementReference? GetContainer { get; set; } = null; + + public ConfirmAutoFocusButton AutoFocusButton { get; set; } + + /// + /// set OK button type for the leftmost button: OK or Yes button + /// + public string OkType + { + get + { + Button1Props ??= new ButtonProps(); + return Button1Props.Type; + } + + set + { + Button1Props ??= new ButtonProps(); + Button1Props.Type = value; + } + } + + #region button text + + /// + /// set OK button content for the leftmost button: OK or Yes button + /// + public OneOf OkText { get => Button1Props.ChildContent; set => Button1Props.ChildContent = value; } + + public OneOf CancelText { get => Button2Props.ChildContent; set => Button2Props.ChildContent = value; } + + /// + /// the leftmost button in LTR layout + /// + internal OneOf Button1Text { get => Button1Props.ChildContent; set => Button1Props.ChildContent = value; } + + /// + /// the secondary button in LTR layout + /// + internal OneOf Button2Text { get => Button2Props.ChildContent; set => Button2Props.ChildContent = value; } + + /// + /// the rightmost button in LTR layout + /// + internal OneOf Button3Text { get => Button3Props.ChildContent; set => Button3Props.ChildContent = value; } + + #endregion + + #region button OnClick callback + + public Func OnCancel { get; set; } + public Func OnOk { get; set; } + + #endregion + + #region button props + + public ButtonProps OkButtonProps { get => Button1Props; set => Button1Props = value; } + public ButtonProps CancelButtonProps { get => Button1Props; set => Button2Props = value; } + + public ButtonProps Button1Props + { + get => _button1Props; + set + { + _button1Props = value; + if (_button1Props != null && _button1Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button1Props.ChildContent.AsT0)) + { + _button1Props.ChildContent = DefaultBtn1Text; + } + } + } + public ButtonProps Button2Props + { + get => _button2Props; + set + { + _button2Props = value; + if (_button2Props != null && _button2Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button2Props.ChildContent.AsT0)) + { + _button2Props.ChildContent = DefaultBtn2Text; + } + } + } + + public ButtonProps Button3Props + { + get => _button3Props; + set + { + _button3Props = value; + if (_button3Props != null && _button3Props.ChildContent.IsT0 && string.IsNullOrWhiteSpace(_button3Props.ChildContent.AsT0)) + { + _button3Props.ChildContent = DefaultBtn3Text; + } + } + } + + private ButtonProps _button1Props = new ButtonProps() { Type = ButtonType.Primary, ChildContent = DefaultBtn1Text }; + private ButtonProps _button2Props = new ButtonProps() { ChildContent = DefaultBtn2Text }; + private ButtonProps _button3Props = new ButtonProps() { ChildContent = DefaultBtn3Text }; + + #endregion + + #region Confirm buttons config + + /// + /// show Cancel button? + /// + public bool OkCancel + { + get => ConfirmButtons != ConfirmButtons.OK; + set + { + if (!value) + { + ConfirmButtons = ConfirmButtons.OK; + } + else + { + ConfirmButtons = ConfirmButtons.OKCancel; + } + } + } + + internal ConfirmButtons ConfirmButtons { get; set; } = ConfirmButtons.OKCancel; + + #endregion + + #region config confirm icon style + internal string ConfirmType { get; set; } = "confirm"; + private ConfirmIcon _confirmIcon; + internal ConfirmIcon ConfirmIcon + { + get => _confirmIcon; + set + { + _confirmIcon = value; + Icon = ConfirmIconRenderFragments.GetByConfirmIcon(value); + if (value == ConfirmIcon.None) + { + ConfirmType = "confirm"; + } + else + { + ConfirmType = value.ToString().ToLower(); + } + } + } + + #endregion + + /// + /// set default options for buttons + /// + internal void BuildButtonsDefaultOptions() + { + // config default button text + switch (ConfirmButtons) + { + case ConfirmButtons.YesNo: + case ConfirmButtons.YesNoCancel: + { + if (this.Button1Text.IsT0) + { + var text = this.Button1Text.AsT0; + if (text == ConfirmOptions.DefaultBtn1Text) + { + this.Button1Text = "Yes"; + } + } + if (this.Button2Text.IsT0) + { + var text = this.Button2Text.AsT0; + if (text == ConfirmOptions.DefaultBtn2Text) + { + this.Button2Text = "No"; + } + } + if (ConfirmButtons == ConfirmButtons.YesNoCancel) + { + if (this.Button3Text.IsT0) + { + var text = this.Button3Text.AsT0; + if (text == ConfirmOptions.DefaultBtn3Text) + { + this.Button3Text = "Cancel"; + } + } + // config button2 defult type + if (this.Button2Props.Danger == null) + { + this.Button2Props.Danger = true; + } + } + break; + } + + case ConfirmButtons.RetryCancel: + { + if (this.Button1Text.IsT0 && this.Button1Text.AsT0 == ConfirmOptions.DefaultBtn1Text) + { + this.Button1Text = "Retry"; + } + break; + } + case ConfirmButtons.AbortRetryIgnore: + { + if (this.Button1Text.IsT0 && this.Button1Text.AsT0 == ConfirmOptions.DefaultBtn1Text) + { + this.Button1Text = "Abort"; + } + if (this.Button2Text.IsT0 && this.Button2Text.AsT0 == ConfirmOptions.DefaultBtn2Text) + { + this.Button2Text = "Retry"; + } + // config button2 defult type + if (this.Button2Props.Danger == null) + { + this.Button2Props.Danger = true; + } + break; + } + default: + break; + } + } } } diff --git a/components/modal/type/ConfirmButtons.cs b/components/modal/type/ConfirmButtons.cs new file mode 100644 index 00000000..a1b74b4b --- /dev/null +++ b/components/modal/type/ConfirmButtons.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace AntDesign +{ + + /// + /// Confirm footer buttons type + /// + public enum ConfirmButtons + { + /// + /// Only a OK button + /// + OK = 0, + + #region two buttons + + /// + /// two buttons: OK and a Cancel + /// + OKCancel = 10, + + /// + /// two buttons: Yes and No + /// + YesNo = 11, + + /// + /// two buttons: Retry and Cancel + /// + RetryCancel = 12, + + #endregion + + #region three buttons + + /// + /// three buttons: Abort, Retry and Ignore + /// + AbortRetryIgnore = 20, + + /// + /// three buttons: Yes, No and Cancel + /// + YesNoCancel = 21, + + #endregion + } +} diff --git a/components/modal/type/ConfirmIcon.cs b/components/modal/type/ConfirmIcon.cs new file mode 100644 index 00000000..44db9ba3 --- /dev/null +++ b/components/modal/type/ConfirmIcon.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.AspNetCore.Components; + +namespace AntDesign +{ + /// + /// Confirm icon type + /// + public enum ConfirmIcon + { + None = 0, + Info = 1, + Warning = 2, + Error = 3, + Success = 4 + } + + internal static class ConfirmIconRenderFragments + { + public static RenderFragment Info = (builder) => + { + builder.OpenComponent(0); + builder.AddAttribute(1, "Type", "info-circle"); + builder.AddAttribute(2, "Theme", "outline"); + builder.CloseComponent(); + }; + + public static RenderFragment Warning = (builder) => + { + builder.OpenComponent(0); + builder.AddAttribute(1, "Type", "exclamation-circle"); + builder.AddAttribute(2, "Theme", "outline"); + builder.CloseComponent(); + }; + + public static RenderFragment Error = (builder) => + { + builder.OpenComponent(0); + builder.AddAttribute(1, "Type", "close-circle"); + builder.AddAttribute(2, "Theme", "outline"); + builder.CloseComponent(); + }; + + public static RenderFragment Success = (builder) => + { + builder.OpenComponent(0); + builder.AddAttribute(1, "Type", "check-circle"); + builder.AddAttribute(2, "Theme", "outline"); + builder.CloseComponent(); + }; + + public static RenderFragment GetByConfirmIcon(ConfirmIcon confirmIcon) + { + switch (confirmIcon) + { + case ConfirmIcon.Info: return Info; + case ConfirmIcon.Warning: return Warning; + case ConfirmIcon.Error: return Error; + case ConfirmIcon.Success: return Success; + default: return null; + } + } + } +} diff --git a/components/modal/type/ConfirmResult.cs b/components/modal/type/ConfirmResult.cs new file mode 100644 index 00000000..5ef401ec --- /dev/null +++ b/components/modal/type/ConfirmResult.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.AspNetCore.Components; +using OneOf; + +namespace AntDesign +{ + /// + /// which the confirm button is clicked + /// + public enum ConfirmResult + { + None = 0, + OK = 1, + Cancel = 2, + Abort = 4, + Retry = 8, + Ignore = 16, + Yes = 32, + No = 64 + } +} diff --git a/components/popconfirm/Popconfirm.razor b/components/popconfirm/Popconfirm.razor index 164b748a..ab01bb52 100644 --- a/components/popconfirm/Popconfirm.razor +++ b/components/popconfirm/Popconfirm.razor @@ -56,7 +56,7 @@ Shape="@CancelButtonProps.Shape" Icon="@CancelButtonProps.Icon" Disabled="@CancelButtonProps.Disabled" - Danger="@CancelButtonProps.Danger"> + Danger="@CancelButtonProps.IsDanger"> @CancelText } @@ -76,7 +76,7 @@ Shape="@OkButtonProps.Shape" Icon="@OkButtonProps.Icon" Disabled="@OkButtonProps.Disabled" - Danger="@OkButtonProps.Danger"> + Danger="@OkButtonProps.IsDanger"> @OkText } diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm.razor index 5e7120c4..832472b5 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm.razor @@ -1,5 +1,5 @@ @inject ModalService _modalService - +@inject MessageService _message @@ -12,6 +12,13 @@ +
+
+ + + + + @code{ Func onOk = (e) => { @@ -49,7 +56,6 @@ OkText = "Yes", OkType = "danger", CancelText = "No", - }); } @@ -71,4 +77,19 @@ } }); } + + + private async Task BlockingConfirm() + { + var content = "Here is a blocking confirm, you can get OK or cancel button is click"; + var title = "Info"; + + var isTrue = await _modalService.ConfirmAsync(new ConfirmOptions() + { + Content = content, + Title = title + }); + + await _message.Info($"The confirm return {isTrue}"); + } } diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmPromise.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmPromise.razor index 2a84f623..4a855b87 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmPromise.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmPromise.razor @@ -13,11 +13,11 @@ await Task.Delay(1000); }; - private async Task ShowConfirm() + private void ShowConfirm() { RenderFragment icon =@; - await _modalService.Confirm(new ConfirmOptions() + _modalService.Confirm(new ConfirmOptions() { Title = "Do you want to delete these items?", Icon = icon, @@ -34,11 +34,11 @@ e.Cancel = true; }; - private async Task ShowConfirmNotClose() + private void ShowConfirmNotClose() { RenderFragment icon =@; - await _modalService.Confirm(new ConfirmOptions() + _modalService.Confirm(new ConfirmOptions() { Title = "Do you want to delete these items?", Icon = icon, diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmRouter.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmRouter.razor index e91d83a3..6ef08c38 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmRouter.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/ConfirmRouter.razor @@ -17,8 +17,7 @@ for (int i = 0; i < 3; i++) { - - await _modalService.Confirm(new ConfirmOptions() + _modalService.Confirm(new ConfirmOptions() { Icon = icon, Content = content, diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm_Service.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm_Service.razor new file mode 100644 index 00000000..cba170ca --- /dev/null +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Confirm_Service.razor @@ -0,0 +1,81 @@ +@inject MessageService _message +@inject ConfirmService _confirmService + + + + + + + + + +
+
+ + + + + + + + + + + +
+
+ + + + + + + + + + + +@code{ + + private async Task ShowConfirm(ConfirmButtons confirmButtons) + { + var content = "Here is a blocking confirm, you can get OK or cancel button is click"; + var title = "Info"; + var confirmResult = await _confirmService.Show(content, title, confirmButtons); + + var _ = _message.Info($"{confirmResult} button is clicked", 2); + } + + private async Task ShowAbortRetryIgnore() + { + var content = "Here is from ConfirmService, you can get which button is click from result"; + var title = "Info"; + var confirmResult = + await _confirmService.Show( + content, + title, + ConfirmButtons.AbortRetryIgnore, + ConfirmIcon.Error, + new ConfirmButtonOptions() + { + Button1Props = new AntDesign.ButtonProps() + { + Type = AntDesign.ButtonType.Dashed, + ChildContent = "Abort" + }, + Button2Props = new AntDesign.ButtonProps() + { + Type = AntDesign.ButtonType.Primary, + Disabled = true, + ChildContent = "Retry" + }, + Button3Props = new AntDesign.ButtonProps() + { + ChildContent = "Ignore" + } + } + ); + + var _ = _message.Info($"{confirmResult} button is clicked", 2); + } +} diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Info.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Info.razor index c1ecb768..6a911a8b 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Info.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Info.razor @@ -15,30 +15,30 @@ @code { - private async Task HandleInfo() + private void HandleInfo() { RenderFragment content =@

some messages...some messages...

some messages...some messages...

; - await _modalService.Info(new ConfirmOptions() + _modalService.Info(new ConfirmOptions() { Title = "This is a notification message", Content = content }); } - private async Task HandleSuccess() + private void HandleSuccess() { - await _modalService.Success(new ConfirmOptions() + _modalService.Success(new ConfirmOptions() { Content = "some messages...some messages..." }); } - private async Task HandleError() + private void HandleError() { - await _modalService.Error(new ConfirmOptions() + _modalService.Error(new ConfirmOptions() { Title = "This is an error message", Content = "some messages...some messages..." diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Locale.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Locale.razor index 28b80c8f..0cc65a3b 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Locale.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Locale.razor @@ -32,9 +32,9 @@ _visible = false; } - private async Task HandleConfirm() + private void HandleConfirm() { - await _modalService.Confirm(new ConfirmOptions() + _modalService.Confirm(new ConfirmOptions() { Title = "Confirm", Icon =@, diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Manual.razor b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Manual.razor index 7d432c41..0455dcbf 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/Manual.razor +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/Manual.razor @@ -13,7 +13,7 @@ Title = "This is a notification message", Content = $"This modal will be destroyed after {secondsToGo} second." }; - var modelRef = await _modalService.Success(props); + var modelRef = _modalService.Success(props); while (secondsToGo > 0) { secondsToGo -= 1; diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm.md b/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm.md index aa9c9a62..c2a74f5b 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm.md +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm.md @@ -12,74 +12,3 @@ title: ## en-US Use `confirm()` to show a confirmation modal dialog. - -```jsx -import { Modal, Button, Space } from 'antd'; -import { ExclamationCircleOutlined } from '@ant-design/icons'; - -const { confirm } = Modal; - -function showConfirm() { - confirm({ - title: 'Do you Want to delete these items?', - icon: , - content: 'Some descriptions', - onOk() { - console.log('OK'); - }, - onCancel() { - console.log('Cancel'); - }, - }); -} - -function showDeleteConfirm() { - confirm({ - title: 'Are you sure delete this task?', - icon: , - content: 'Some descriptions', - okText: 'Yes', - okType: 'danger', - cancelText: 'No', - onOk() { - console.log('OK'); - }, - onCancel() { - console.log('Cancel'); - }, - }); -} - -function showPropsConfirm() { - confirm({ - title: 'Are you sure delete this task?', - icon: , - content: 'Some descriptions', - okText: 'Yes', - okType: 'danger', - okButtonProps: { - disabled: true, - }, - cancelText: 'No', - onOk() { - console.log('OK'); - }, - onCancel() { - console.log('Cancel'); - }, - }); -} - -ReactDOM.render( - - - - - , - mountNode, -); -``` diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm_service.md b/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm_service.md new file mode 100644 index 00000000..3e0f466c --- /dev/null +++ b/site/AntBlazor.Docs/Demos/Components/Modal/demo/confirm_service.md @@ -0,0 +1,14 @@ +--- +order: 13 +title: + zh-CN: ConfirmService + en-US: ConfirmService +--- + +## zh-CN + +使用 `ConfirmService.Show` 可以快捷地弹出一个内置的确认框,类似于 Windows MessageBox。 + +## en-US + +Use `ConfirmService.Show` to show a built-in confirm dialog, similar to Windows MessageBox. diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.en-US.md b/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.en-US.md index 2a6cc567..0cba44eb 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.en-US.md +++ b/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.en-US.md @@ -57,8 +57,14 @@ There are five ways to display the information based on the content's nature: - `ModalService.Warning` - `ModalService.Confirm` - `ModalService.CreateAsync` +- `ModalService.ConfirmAsync` +- `ModalService.InfoAsync` +- `ModalService.SuccessAsync` +- `ModalService.ErrorAsync` +- `ModalService.WarningAsync` > Please confirm that the `` component has been added to `App.Razor`. +> `ConfirmAsync`、`InfoAsync`、`SuccessAsync`、`ErrorAsync`、`WarningAsync` will return Task,it can be used to determine whether the button the user clicks is an OK button (true) or a cancel button (false) #### ConfirmOptions diff --git a/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.zh-CN.md b/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.zh-CN.md index 2ca073b9..02658343 100644 --- a/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.zh-CN.md +++ b/site/AntBlazor.Docs/Demos/Components/Modal/doc/index.zh-CN.md @@ -60,8 +60,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/3StSdUlSH/Modal.svg - `ModalService.Warning` - `ModalService.Confirm` - `ModalService.CreateAsync` +- `ModalService.ConfirmAsync` +- `ModalService.InfoAsync` +- `ModalService.SuccessAsync` +- `ModalService.ErrorAsync` +- `ModalService.WarningAsync` > 请确认已经在 `App.Razor` 中添加了 `` 组件。 +> `ConfirmAsync`、`InfoAsync`、`SuccessAsync`、`ErrorAsync`、`WarningAsync` 返回值为Task,可用于判断用户点击的按钮是 OK按钮(true) 还是 Cancel按钮(false) #### ConfirmOptions