diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs index 53c56295ce..b53b2b4d56 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs @@ -1,14 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.ViewFeatures; +using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.TagHelpers; -using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; -using Volo.Abp.Threading; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers { @@ -52,4 +43,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers return Task.CompletedTask; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs index 1d6204373a..5f649db448 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs @@ -1,6 +1,7 @@ -using System.Collections.Generic; -using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Collections.Generic; +using System.Text.Encodings.Web; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; @@ -14,6 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb { _encoder = encoder; } + public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "li"; @@ -24,7 +26,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb var list = context.GetValue>(BreadcrumbItemsContent); output.Content.SetHtmlContent(GetInnerHtml(context, output)); - + list.Add(new BreadcrumbItem { Html = output.Render(_encoder), @@ -39,10 +41,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb if (string.IsNullOrWhiteSpace(TagHelper.Href)) { output.Attributes.Add("aria-current", "page"); - return TagHelper.Title; + return _encoder.Encode(TagHelper.Title); } - return "" + TagHelper.Title + ""; - } + var link = new TagBuilder("a"); + link.Attributes.Add("href", TagHelper.Href); + link.InnerHtml.Append(TagHelper.Title); + return link.ToHtmlString(); + } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs index 1d0476c5ad..4b433ac495 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs @@ -1,8 +1,8 @@ -using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb { @@ -10,37 +10,37 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb { public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { + output.TagName = "nav"; + output.Attributes.Add("aria-label", "breadcrumb"); + var list = InitilizeFormGroupContentsContext(context, output); await output.GetChildContentAsync(); - SetInnerOlTag(context, output); - SetInnerList(context, output, list); + var listTagBuilder = GetOlTagBuilder(); - output.TagName = "nav"; - output.Attributes.Add("aria-label", "breadcrumb"); + SetInnerList(context, output, list, listTagBuilder); + + output.Content.SetHtmlContent(listTagBuilder); } - protected virtual void SetInnerOlTag(TagHelperContext context, TagHelperOutput output) + protected virtual TagBuilder GetOlTagBuilder() { - output.PreContent.SetHtmlContent("
    "); - output.PostContent.SetHtmlContent("
"); + var builder = new TagBuilder("ol"); + builder.AddCssClass("breadcrumb"); + return builder; } - protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List list) + protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List list, TagBuilder listTagBuilder) { SetLastOneActiveIfThereIsNotAny(context, output, list); - var html = new StringBuilder(""); - foreach (var breadcrumbItem in list) { var htmlPart = SetActiveClassIfActiveAndGetHtml(breadcrumbItem); - html.AppendLine(htmlPart); + listTagBuilder.InnerHtml.AppendHtml(htmlPart); } - - output.Content.SetHtmlContent(html.ToString()); } protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs index 56143ea059..f7ffa84c39 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs @@ -19,6 +19,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button public FontIconType IconType { get; set; } = FontIconType.FontAwesome; + public bool BusyTextIsHtml { get; set; } + public AbpButtonTagHelper(AbpButtonTagHelperService service) : base(service) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs index 63a61fd1f2..fb74d5c1da 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs @@ -1,13 +1,14 @@ -using System; -using Localization.Resources.AbpUi; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Localization; +using System; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button { public class AbpButtonTagHelperService : AbpButtonTagHelperServiceBase { protected const string DataBusyTextAttributeName = "data-busy-text"; + protected const string DataBusyTextIsHtmlAttributeName = "data-busy-text-is-html"; protected IStringLocalizer L { get; } @@ -22,6 +23,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button output.TagName = "button"; AddType(context, output); AddBusyText(context, output); + AddBusyTextIsHtml(context, output); } protected virtual void AddType(TagHelperContext context, TagHelperOutput output) @@ -44,5 +46,15 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button output.Attributes.SetAttribute(DataBusyTextAttributeName, busyText); } + + protected virtual void AddBusyTextIsHtml(TagHelperContext context, TagHelperOutput output) + { + if (!TagHelper.BusyTextIsHtml) + { + return; + } + + output.Attributes.SetAttribute(DataBusyTextIsHtmlAttributeName, TagHelper.BusyTextIsHtml.ToString().ToLower()); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs index 419aff7c08..ab35dbe804 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; using System; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; @@ -43,7 +44,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button return; } - output.Content.AppendHtml($" "); + var icon = new TagBuilder("i"); + icon.AddCssClass(GetIconClass(context, output)); + output.Content.AppendHtml(icon); } protected virtual string GetIconClass(TagHelperContext context, TagHelperOutput output) @@ -64,7 +67,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button return; } - output.Content.AppendHtml($"{TagHelper.Text}"); + var span = new TagBuilder("span"); + span.InnerHtml.Append(TagHelper.Text); + output.Content.AppendHtml(span); } protected virtual void AddDisabled(TagHelperContext context, TagHelperOutput output) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs index 5a4bafd47d..d3736a384a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using System.Text; -using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Collections.Generic; +using System.Text.Encodings.Web; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; @@ -42,8 +42,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel protected virtual void SetInnerImgTag(TagHelperContext context, TagHelperOutput output) { - var imgTag ="\"""; - output.Content.SetHtmlContent(imgTag); + var img = new TagBuilder("img"); + img.AddCssClass("d-block w-100"); + img.Attributes.Add("src", TagHelper.Src); + img.Attributes.Add("alt", TagHelper.Alt); + + output.Content.SetHtmlContent(img); } protected virtual void SetActive(TagHelperContext context, TagHelperOutput output) @@ -61,15 +65,19 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel return; } - var html = new StringBuilder(""); + var title = new TagBuilder("h5"); + title.InnerHtml.Append(TagHelper.CaptionTitle); + + var caption = new TagBuilder("p"); + caption.InnerHtml.Append(TagHelper.Caption); - html.AppendLine("
"); - html.AppendLine("
"+TagHelper.CaptionTitle+"
"); - html.AppendLine("

" + TagHelper.Caption + "

"); - html.AppendLine("
"); + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("carousel-caption d-none d-md-block"); + wrapper.InnerHtml.AppendHtml(title); + wrapper.InnerHtml.AppendHtml(caption); - output.PostContent.SetHtmlContent(html.ToString()); + output.PostContent.SetHtmlContent(wrapper); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs index c92e08365e..c3672db7f5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs @@ -1,15 +1,24 @@ -using System; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; +using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel { public class AbpCarouselTagHelperService : AbpTagHelperService { + protected IStringLocalizer L { get; } + + public AbpCarouselTagHelperService(IStringLocalizer localizer) + { + L = localizer; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; @@ -37,18 +46,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel protected virtual void SetItems(TagHelperContext context, TagHelperOutput output, List itemList) { - var itemsHtml = new StringBuilder(""); - itemsHtml.Append("
"); + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("carousel-inner"); foreach (var carouselItem in itemList) { SetActiveIfActive(carouselItem); - itemsHtml.AppendLine(carouselItem.Html); + wrapper.InnerHtml.AppendHtml(carouselItem.Html); } - itemsHtml.Append("
"); - output.Content.SetHtmlContent(itemsHtml.ToString()); + output.Content.SetHtmlContent(wrapper); } protected virtual void SetControls(TagHelperContext context, TagHelperOutput output, List itemList) @@ -58,18 +66,45 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel return; } - var html = new StringBuilder(""); - - html.AppendLine(""); - html.AppendLine(""); - html.AppendLine("Previous"); - html.AppendLine(""); - html.AppendLine(""); - html.AppendLine(""); - html.AppendLine("Next"); - html.AppendLine(""); - - output.PostContent.SetHtmlContent(html.ToString()); + // create 'previous' item + var prevIcon = new TagBuilder("span"); + prevIcon.AddCssClass("carousel-control-prev-icon"); + prevIcon.Attributes.Add("aria-hidden", "true"); + + var prevText = new TagBuilder("span"); + prevText.AddCssClass("sr-only"); + prevText.InnerHtml.Append(L["Previous"].Value); + + var prevAnchor = new TagBuilder("a"); + prevAnchor.AddCssClass("carousel-control-prev"); + prevAnchor.Attributes.Add("href", "#" + TagHelper.Id); + prevAnchor.Attributes.Add("role", "button"); + prevAnchor.Attributes.Add("data-slide", "prev"); + + prevAnchor.InnerHtml.AppendHtml(prevIcon); + prevAnchor.InnerHtml.AppendHtml(prevText); + + // create 'next' item + var nextIcon = new TagBuilder("span"); + nextIcon.AddCssClass("carousel-control-next-icon"); + nextIcon.Attributes.Add("aria-hidden", "true"); + + var nextText = new TagBuilder("span"); + nextText.AddCssClass("sr-only"); + nextText.InnerHtml.Append(L["Next"].Value); + + var nextAnchor = new TagBuilder("a"); + nextAnchor.AddCssClass("carousel-control-next"); + nextAnchor.Attributes.Add("href", "#" + TagHelper.Id); + nextAnchor.Attributes.Add("role", "button"); + nextAnchor.Attributes.Add("data-slide", "next"); + + nextAnchor.InnerHtml.AppendHtml(nextIcon); + nextAnchor.InnerHtml.AppendHtml(nextText); + + // append post content + output.PostContent.AppendHtml(prevAnchor); + output.PostContent.AppendHtml(nextAnchor); } protected virtual void SetIndicators(TagHelperContext context, TagHelperOutput output, List itemList) @@ -79,20 +114,24 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel return; } - var html = new StringBuilder("
    "); + var list = new TagBuilder("ol"); + list.AddCssClass("carousel-indicators"); for (var i = 0; i < itemList.Count; i++) { - html.AppendLine( - "
  1. " : "") + - "
  2. "); + var listItem = new TagBuilder("li"); + listItem.Attributes.Add("data-target", "#" + TagHelper.Id); + listItem.Attributes.Add("data-slide-to", i.ToString()); + + if (itemList[i].Active) + { + listItem.AddCssClass("active"); + } + + list.InnerHtml.AppendHtml(listItem); } - html.AppendLine("
"); - output.PreContent.SetHtmlContent(html.ToString()); + output.PreContent.SetHtmlContent(list); } protected virtual void SetOneItemAsActive(TagHelperContext context, TagHelperOutput output, List itemList) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs index 74365b0c8a..6e532cb71d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs @@ -1,7 +1,8 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse @@ -17,7 +18,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, innerContent); var tabHeaderItems = context.GetValue>(AccordionItems); - tabHeaderItems.Add(html); output.SuppressOutput(); @@ -25,23 +25,43 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse protected virtual string GetAccordionHeaderItem(TagHelperContext context, TagHelperOutput output) { - return "
" + Environment.NewLine + - "
" + Environment.NewLine + - " " + Environment.NewLine + - "
" + Environment.NewLine + - "
" + Environment.NewLine; + var button = new TagBuilder("button"); + button.AddCssClass("btn btn-link"); + button.Attributes.Add("type", "button"); + button.Attributes.Add("data-toggle", "collapse"); + button.Attributes.Add("data-target", "#" + GetContentId()); + button.Attributes.Add("aria-expanded", "true"); + button.Attributes.Add("aria-controls", GetContentId()); + button.InnerHtml.Append(TagHelper.Title); + + var h5 = new TagBuilder("h5"); + h5.AddCssClass("mb-0"); + h5.InnerHtml.AppendHtml(button); + + var header = new TagBuilder("div"); + header.AddCssClass("card-header"); + header.Attributes.Add("id", GetHeadingId()); + header.InnerHtml.AppendHtml(h5); + + return header.ToHtmlString(); } protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, string content) { var show = (TagHelper.Active ?? false) ? " show" : ""; - return "
" + Environment.NewLine + - "
" + Environment.NewLine + - content + Environment.NewLine + - "
" + Environment.NewLine + - "
" + Environment.NewLine; + + var cardBody = new TagBuilder("div"); + cardBody.AddCssClass("card-body"); + cardBody.InnerHtml.AppendHtml(content); + + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("collapse" + show); + wrapper.Attributes.Add("id", GetContentId()); + wrapper.Attributes.Add("aria-labelledby", GetHeadingId()); + wrapper.Attributes.Add("data-parent", "#" + AbpAccordionParentIdPlaceholder); + wrapper.InnerHtml.AppendHtml(cardBody); + + return wrapper.ToHtmlString(); } protected virtual string GetHeadingId() diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs index 20e62604a9..c7f93e87cc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs @@ -1,14 +1,22 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse { public class AbpAccordionTagHelperService : AbpTagHelperService { + protected IHtmlGenerator HtmlGenerator { get; } + + public AbpAccordionTagHelperService(IHtmlGenerator htmlGenerator) + { + HtmlGenerator = htmlGenerator; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetRandomIdIfNotProvided(); @@ -22,26 +30,21 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse await output.GetChildContentAsync(); - var content = GetContent(items); - - output.Content.SetHtmlContent(content); + SetContent(context, output, items); } - protected virtual string GetContent(List items) + protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List items) { - var html = new StringBuilder(""); foreach (var item in items) { - var content = item.Replace(AbpAccordionParentIdPlaceholder, TagHelper.Id); + var content = item.Replace(AbpAccordionParentIdPlaceholder, HtmlGenerator.Encode(TagHelper.Id)); - html.AppendLine( - "
" + Environment.NewLine + - content - + "
" + Environment.NewLine - ); - } + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("card"); + wrapper.InnerHtml.AppendHtml(content); - return html.ToString(); + output.Content.AppendHtml(wrapper); + } } protected virtual List InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 58a88c676f..5bebab0257 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -1,12 +1,13 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.TagHelpers; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text.Encodings.Web; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.TagHelpers; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; @@ -249,7 +250,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { if (IsOutputHidden(inputTag) || TagHelper.SuppressLabel) { - return ""; + return string.Empty; } if (string.IsNullOrEmpty(TagHelper.Label)) @@ -257,11 +258,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox) + GetRequiredSymbol(context, output); } - var checkboxClass = isCheckbox ? "class=\"custom-control-label\" " : ""; + var label = new TagBuilder("label"); + label.Attributes.Add("for", GetIdAttributeValue(inputTag)); + label.InnerHtml.Append(TagHelper.Label); + + if (isCheckbox) + { + label.AddCssClass("custom-control-label"); + } - return "" + GetRequiredSymbol(context, output); + return label.ToHtmlString(); } protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output) @@ -308,9 +314,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); var localizedText = _tagHelperLocalizer.GetLocalizedText(text, TagHelper.AspFor.ModelExplorer); - return "" + - localizedText + - ""; + var small = new TagBuilder("small"); + small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText"); + small.AddCssClass("form-text text-muted"); + + return small.ToHtmlString(); } protected virtual async Task GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, TagHelperOutput output, bool isCheckbox) @@ -426,11 +434,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return inputTag.Attributes.Any(a => a.Name.ToLowerInvariant() == "type" && a.Value.ToString().ToLowerInvariant() == "hidden"); } - protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag) + protected virtual string GetIdAttributeValue(TagHelperOutput inputTag) { var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); - return idAttr != null ? "for=\"" + idAttr.Value + "\"" : ""; + return idAttr != null ? idAttr.Value.ToString() : string.Empty; + } + + protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag) + { + var id = GetIdAttributeValue(inputTag); + + return !string.IsNullOrWhiteSpace(id) ? "for=\"" + id + "\"" : string.Empty; } protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs index bcfa5bd7d1..8d5c704830 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs @@ -1,12 +1,12 @@ +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.AspNetCore.Razor.TagHelpers; -using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @@ -53,15 +53,35 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var inlineClass = (TagHelper.Inline ?? false) ? " custom-control-inline" : ""; var id = TagHelper.AspFor.Name + "Radio" + selectItem.Value; var name = TagHelper.AspFor.Name; - var selected = selectItem.Selected ? " checked=\"checked\"" : ""; - var disabled = (TagHelper.Disabled??false) ? " disabled" : ""; - var htmlPart = "
\r\n" + - " \r\n" + - " \r\n" + - "
"; + var input = new TagBuilder("input"); + input.AddCssClass("custom-control-input"); + input.Attributes.Add("type", "radio"); + input.Attributes.Add("id", id); + input.Attributes.Add("name", name); + input.Attributes.Add("value", selectItem.Value); + + if (selectItem.Selected) + { + input.Attributes.Add("checked", "checked"); + } + + if (TagHelper.Disabled ?? false) + { + input.Attributes.Add("disabled", "disabled"); + } + + var label = new TagBuilder("label"); + label.AddCssClass("custom-control-label"); + label.Attributes.Add("for", id); + label.InnerHtml.Append(selectItem.Text); + + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("custom-control custom-radio" + inlineClass); + wrapper.InnerHtml.AppendHtml(input); + wrapper.InnerHtml.AppendHtml(label); - html.AppendLine(htmlPart); + html.AppendLine(wrapper.ToHtmlString()); } return html.ToString(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index 21f6c498a9..017d58dc17 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -1,20 +1,18 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.TagHelpers; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Dynamic.Core; using System.Text.Encodings.Web; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.AspNetCore.Mvc.TagHelpers; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.AspNetCore.Razor.TagHelpers; -using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; -using Volo.Abp.DynamicProxy; using Volo.Abp.Localization; -using Volo.Abp.Reflection; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { @@ -26,9 +24,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form private readonly IStringLocalizerFactory _stringLocalizerFactory; public AbpSelectTagHelperService( - IHtmlGenerator generator, - HtmlEncoder encoder, - IAbpTagHelperLocalizer tagHelperLocalizer, + IHtmlGenerator generator, + HtmlEncoder encoder, + IAbpTagHelperLocalizer tagHelperLocalizer, IStringLocalizerFactory stringLocalizerFactory) { _generator = generator; @@ -140,7 +138,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form { if (!string.IsNullOrEmpty(TagHelper.Label)) { - return "" + GetRequiredSymbol(context, output); + var label = new TagBuilder("label"); + label.Attributes.Add("for", GetIdAttributeValue(selectTag)); + label.InnerHtml.Append(TagHelper.Label); + + return label.ToHtmlString() + GetRequiredSymbol(context, output); } return await GetLabelAsHtmlUsingTagHelperAsync(context, output) + GetRequiredSymbol(context, output); @@ -199,9 +201,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); var localizedText = _tagHelperLocalizer.GetLocalizedText(text, TagHelper.AspFor.ModelExplorer); - return "" + - localizedText + - ""; + var small = new TagBuilder("small"); + small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText"); + small.AddCssClass("form-text text-muted"); + + return small.ToHtmlString(); } protected virtual List GetSelectItemsFromEnum(TagHelperContext context, TagHelperOutput output, ModelExplorer explorer) @@ -338,11 +342,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form } } - protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag) + protected virtual string GetIdAttributeValue(TagHelperOutput inputTag) { var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); - return idAttr != null ? "for=\"" + idAttr.Value + "\"" : ""; + return idAttr != null ? idAttr.Value.ToString() : string.Empty; + } + + protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag) + { + var id = GetIdAttributeValue(inputTag); + + return !string.IsNullOrWhiteSpace(id) ? "for=\"" + id + "\"" : string.Empty; } protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs index 38cac85a6d..1bc6ab2f3a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs @@ -1,60 +1,106 @@ -using System.Text; -using Localization.Resources.AbpUi; -using Microsoft.AspNetCore.Razor.TagHelpers; -using Microsoft.Extensions.Localization; -using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal -{ - public class AbpModalFooterTagHelperService : AbpTagHelperService - { - private readonly IStringLocalizer _localizer; - - public AbpModalFooterTagHelperService(IStringLocalizer localizer) - { - _localizer = localizer; - } - - public override void Process(TagHelperContext context, TagHelperOutput output) - { - output.TagName = "div"; - output.Attributes.AddClass("modal-footer"); - - if (TagHelper.Buttons != AbpModalButtons.None) - { - output.PostContent.SetHtmlContent(CreateContent()); - } - ProcessButtonsAlignment(output); - } - - protected virtual string CreateContent() - { - var sb = new StringBuilder(); - - switch (TagHelper.Buttons) - { - case AbpModalButtons.Cancel: - sb.AppendLine(""); - break; - case AbpModalButtons.Close: - sb.AppendLine(""); - break; - case AbpModalButtons.Save: - sb.AppendLine(""); - break; - case AbpModalButtons.Save | AbpModalButtons.Cancel: - sb.AppendLine(""); - sb.AppendLine(""); - break; - case AbpModalButtons.Save | AbpModalButtons.Close: - sb.AppendLine(""); - sb.AppendLine(""); - break; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; +using System.Text; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +{ + public class AbpModalFooterTagHelperService : AbpTagHelperService + { + private readonly IStringLocalizer _localizer; + + public AbpModalFooterTagHelperService(IStringLocalizer localizer) + { + _localizer = localizer; + } + + public override void Process(TagHelperContext context, TagHelperOutput output) + { + output.TagName = "div"; + output.Attributes.AddClass("modal-footer"); + + if (TagHelper.Buttons != AbpModalButtons.None) + { + output.PostContent.SetHtmlContent(CreateContent()); + } + + ProcessButtonsAlignment(output); + } + + protected virtual string CreateContent() + { + var sb = new StringBuilder(); + + switch (TagHelper.Buttons) + { + case AbpModalButtons.Cancel: + sb.AppendLine(GetCancelButton()); + break; + case AbpModalButtons.Close: + sb.AppendLine(GetCloseButton()); + break; + case AbpModalButtons.Save: + sb.AppendLine(GetSaveButton()); + break; + case AbpModalButtons.Save | AbpModalButtons.Cancel: + sb.AppendLine(GetSaveButton()); + sb.AppendLine(GetCancelButton()); + break; + case AbpModalButtons.Save | AbpModalButtons.Close: + sb.AppendLine(GetSaveButton()); + sb.AppendLine(GetCloseButton()); + break; } - return sb.ToString(); - } - + return sb.ToString(); + } + + protected virtual string GetSaveButton() + { + var icon = new TagBuilder("i"); + icon.AddCssClass("fa"); + icon.AddCssClass("fa-check"); + + var span = new TagBuilder("span"); + span.InnerHtml.Append(_localizer["Save"]); + + var element = new TagBuilder("button"); + element.Attributes.Add("type", "submit"); + element.AddCssClass("btn"); + element.AddCssClass("btn-primary"); + element.Attributes.Add("data-busy-text", _localizer["SavingWithThreeDot"]); + element.InnerHtml.AppendHtml(icon); + element.InnerHtml.AppendHtml(span); + + return element.ToHtmlString(); + } + + protected virtual string GetCloseButton() + { + var element = new TagBuilder("button"); + element.Attributes.Add("type", "button"); + element.Attributes.Add("data-dismiss", "modal"); + element.AddCssClass("btn"); + element.AddCssClass("btn-secondary"); + element.InnerHtml.Append(_localizer["Close"]); + + return element.ToHtmlString(); + } + + protected virtual string GetCancelButton() + { + var element = new TagBuilder("button"); + element.Attributes.Add("type", "button"); + element.Attributes.Add("data-dismiss", "modal"); + element.AddCssClass("btn"); + element.AddCssClass("btn-secondary"); + element.InnerHtml.Append(_localizer["Cancel"]); + + return element.ToHtmlString(); + } + protected virtual void ProcessButtonsAlignment(TagHelperOutput output) { if (TagHelper.ButtonAlignment == ButtonsAlign.Default) @@ -62,6 +108,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal return; } output.Attributes.AddClass("justify-content-" + TagHelper.ButtonAlignment.ToString().ToLowerInvariant()); - } - } -} \ No newline at end of file + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs index 79cddd1f53..7473245e96 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs @@ -1,11 +1,20 @@ -using System.Text; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal { public class AbpModalHeaderTagHelperService : AbpTagHelperService { + protected IStringLocalizer L { get; } + + public AbpModalHeaderTagHelperService(IStringLocalizer localizer) + { + L = localizer; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; @@ -16,22 +25,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal protected virtual string CreatePreContent() { - var sb = new StringBuilder(); - - sb.AppendLine("
" + TagHelper.Title + "
"); + var title = new TagBuilder("h5"); + title.AddCssClass("modal-title"); + title.InnerHtml.Append(TagHelper.Title); - return sb.ToString(); + return title.ToHtmlString(); } protected virtual string CreatePostContent() { - var sb = new StringBuilder(); - - sb.AppendLine(" "); + var span = new TagBuilder("span"); + span.Attributes.Add("aria-hidden", "true"); + span.InnerHtml.AppendHtml("×"); + + var button = new TagBuilder("button"); + button.AddCssClass("close"); + button.Attributes.Add("type", "button"); + button.Attributes.Add("data-dismiss", "modal"); + button.Attributes.Add("aria-label", L["Close"].Value); + button.InnerHtml.AppendHtml(span); - return sb.ToString(); + return button.ToHtmlString(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs index 3524b27d35..78d664b562 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs @@ -1,30 +1,66 @@ -using System.Linq; -using System.Text; +using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; - +using System.Text; +using System.Threading.Tasks; + namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal { public class AbpModalTagHelperService : AbpTagHelperService { - public override void Process(TagHelperContext context, TagHelperOutput output) + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { output.TagName = null; - output.PreContent.SetHtmlContent(CreatePreContent(output)); - output.PostContent.SetHtmlContent(CreatePostContent()); - } - protected virtual string CreatePreContent(TagHelperOutput output) - { - var sb = new StringBuilder(); + var childContent = await output.GetChildContentAsync(); + + SetContent(context, output, childContent); + } - var attritubutes = output.Attributes.Select(a => " " + a.Name + "=\"" + a.Value + "\" ").ToList(); - var attritubutesAsJoin = string.Join(" ", attritubutes.ToArray()); + protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent) + { + var modalContent = GetModalContentElement(context, output, childContent); + var modalDialog = GetModalDialogElement(context, output, modalContent); + var modal = GetModal(context, output, modalDialog); - sb.AppendLine("
"); - sb.AppendLine("
"); - sb.AppendLine("
"); + output.Content.SetHtmlContent(modal); + } + + protected virtual TagBuilder GetModalContentElement(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent) + { + var element = new TagBuilder("div"); + element.AddCssClass(GetModalContentClasses()); + element.InnerHtml.SetHtmlContent(childContent); + return element; + } - return sb.ToString(); + protected virtual TagBuilder GetModalDialogElement(TagHelperContext context, TagHelperOutput output, IHtmlContent innerHtml) + { + var element = new TagBuilder("div"); + element.AddCssClass(GetModalDialogClasses()); + element.Attributes.Add("role", "document"); + element.InnerHtml.SetHtmlContent(innerHtml); + return element; + } + + protected virtual TagBuilder GetModal(TagHelperContext context, TagHelperOutput output, IHtmlContent innerHtml) + { + var element = new TagBuilder("div"); + element.AddCssClass(GetModalClasses()); + element.Attributes.Add("tabindex", "-1"); + element.Attributes.Add("role", "dialog"); + element.Attributes.Add("aria-hidden", "true"); + + foreach (var attr in output.Attributes) + { + element.Attributes.Add(attr.Name, attr.Value.ToString()); + } + + SetDataAttributes(element); + + element.InnerHtml.SetHtmlContent(innerHtml); + + return element; } protected virtual string GetModalClasses() @@ -63,17 +99,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal return "data-backdrop=\"static\" "; } return string.Empty; - } - - protected virtual string CreatePostContent() - { - var sb = new StringBuilder(); - - sb.AppendLine("
"); - sb.AppendLine("
"); - sb.AppendLine("
"); - - return sb.ToString(); + } + + protected virtual void SetDataAttributes(TagBuilder builder) + { + if (TagHelper.Static == true) + { + builder.Attributes.Add("data-backdrop", "static"); + } } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs index 1b53894ac2..df48452c40 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs @@ -1,11 +1,21 @@ -using System; +using Localization.Resources.AbpUi; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Localization; +using System; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Nav { public class AbpNavbarToggleTagHelperService : AbpTagHelperService { + protected IStringLocalizer L { get; } + + public AbpNavbarToggleTagHelperService(IStringLocalizer stringLocalizer) + { + L = stringLocalizer; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { SetRandomNameIfNotProvided(); @@ -18,10 +28,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Nav protected virtual void SetToggleButton(TagHelperContext context, TagHelperOutput output) { - output.PreElement.SetHtmlContent( - ""); + var span = new TagBuilder("span"); + span.AddCssClass("navbar-toggler-icon"); + + var button = new TagBuilder("button"); + button.AddCssClass("navbar-toggler"); + button.Attributes.Add("type", "button"); + button.Attributes.Add("data-toggle", "collapse"); + button.Attributes.Add("data-target", "#" + TagHelper.Id); + button.Attributes.Add("aria-controls", TagHelper.Id); + button.Attributes.Add("aria-expanded", "false"); + button.Attributes.Add("aria-label", L["ToggleNavigation"].Value); + button.InnerHtml.AppendHtml(span); + + output.PreElement.SetHtmlContent(button); } protected virtual void SetRandomNameIfNotProvided() diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs index 9c37e77767..71f3bfe247 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs @@ -1,13 +1,13 @@ -using System; -using System.Linq; -using System.Text; -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using Localization.Resources.AbpUi; +using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Mvc.TagHelpers; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Localization; +using System; +using System.Linq; +using System.Text; +using System.Text.Encodings.Web; +using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; @@ -134,7 +134,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination SetHrefAttribute(currentPage, attributeList); - tagHelperOutput.Content.SetHtmlContent(localizer[localizationKey]); + tagHelperOutput.Content.SetContent(localizer[localizationKey]); var renderedHtml = tagHelperOutput.Render(_encoder); @@ -166,7 +166,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination var localizer = _stringLocalizerFactory.Create(typeof(AbpUiResource)); var pagerInfo = (TagHelper.ShowInfo ?? false) ? - "
" + localizer["PagerInfo{0}{1}{2}", TagHelper.Model.ShowingFrom, TagHelper.Model.ShowingTo, TagHelper.Model.TotalItemsCount] + "
\r\n" + "
" + _encoder.Encode(localizer["PagerInfo{0}{1}{2}", TagHelper.Model.ShowingFrom, TagHelper.Model.ShowingTo, TagHelper.Model.TotalItemsCount]) + "
\r\n" : ""; return diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs index 7ecb351290..5ada0dfbc5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs @@ -1,11 +1,20 @@ -using System; -using System.Linq; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; - +using System.Linq; +using System.Web; + namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover { public class AbpPopoverTagHelperService : AbpTagHelperService - { + { + protected IHtmlGenerator HtmlGenerator { get; } + + public AbpPopoverTagHelperService(IHtmlGenerator htmlGenerator) + { + HtmlGenerator = htmlGenerator; + } + public override void Process(TagHelperContext context, TagHelperOutput output) { if (!TagHelper.Disabled ?? true) @@ -21,38 +30,51 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover SetDisabled(context, output); } } + protected virtual void SetDisabled(TagHelperContext context, TagHelperOutput output) - { - var triggerAsHtml = TagHelper.Dismissible ?? false ? "data-trigger=\"focus\" " : ""; + { + var triggerValue = TagHelper.Dismissible ?? false ? "focus" : ""; if (TagHelper.Hoverable ?? false) { - if (triggerAsHtml.Contains("focus")) + if (triggerValue.Contains("focus")) { - triggerAsHtml = triggerAsHtml.Replace("focus", "focus hover"); + triggerValue = triggerValue.Replace("focus", "focus hover"); } else { - triggerAsHtml = "data-trigger=\"hover\" "; + triggerValue = "hover"; } - } - var dataPlacementAsHtml = "data-placement=\"" + GetDirectory().ToString().ToLowerInvariant() + "\" "; - + } + + var dataPlacement = GetDirectory().ToString().ToLowerInvariant(); // data-placement="default" with data-trigger="focus" causes Cannot read property 'indexOf' of undefined at computeAutoPlacement(bootstrap.bundle.js?_v=637146714627330435:2185) error if (IsDismissibleOrHoverable() && GetDirectory() == PopoverDirectory.Default) { //dataPlacementAsHtml = string.Empty; //bootstrap default placement is right, abp's is top. - dataPlacementAsHtml = dataPlacementAsHtml.Replace("default", "top"); + dataPlacement = dataPlacement.Replace("default", "top"); } + var titleAttribute = output.Attributes.FirstOrDefault(at => at.Name == "title"); - var titleAsHtml = titleAttribute == null ? "" : "title=\"" + titleAttribute.Value + "\" "; - var preElementHtml = ""; - var postElementHtml = ""; - output.PreElement.SetHtmlContent(preElementHtml); - output.PostElement.SetHtmlContent(postElementHtml); + var span = new TagBuilder("span"); + span.AddCssClass("d-inline-block"); + span.Attributes.Add("tabindex", "0"); + span.Attributes.Add("data-toggle", "popover"); + span.Attributes.Add("data-content", GetDataContent()); + span.Attributes.Add("data-trigger", triggerValue); + span.Attributes.Add("data-placement", dataPlacement); + + if (titleAttribute != null) + { + span.Attributes.Add("title", HttpUtility.HtmlDecode(titleAttribute.Value.ToString())); + } + + output.PreElement.SetHtmlContent(span.RenderStartTag()); + output.PostElement.SetHtmlContent(span.RenderEndTag()); output.Attributes.Add("style", "pointer-events: none;"); } + protected virtual void SetDataTriggerIfDismissible(TagHelperContext context, TagHelperOutput output) { if (TagHelper.Dismissible ?? false) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs index fb724af9c8..8746e4a48b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs @@ -1,7 +1,8 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab @@ -31,14 +32,26 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab var link = TagHelper.Name; var title = TagHelper.Title; - return "
  • " + - "" + - title + - "" + - "
    " + - AbpTabDropdownItemsActivePlaceholder + - "
    " + - "
  • "; + var anchor = new TagBuilder("a"); + anchor.AddCssClass("nav-link dropdown-toggle"); + anchor.Attributes.Add("id", id); + anchor.Attributes.Add("data-toggle", "dropdown"); + anchor.Attributes.Add("href", "#" + link); + anchor.Attributes.Add("role", "button"); + anchor.Attributes.Add("aria-haspopup", "true"); + anchor.Attributes.Add("aria-expanded", "false"); + anchor.InnerHtml.Append(title); + + var menu = new TagBuilder("div"); + menu.AddCssClass("dropdown-menu"); + menu.InnerHtml.Append(AbpTabDropdownItemsActivePlaceholder); + + var listItem = new TagBuilder("li"); + listItem.AddCssClass("nav-item dropdown"); + listItem.InnerHtml.AppendHtml(anchor); + listItem.InnerHtml.AppendHtml(menu); + + return listItem.ToHtmlString(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs index 54a29bf691..1955127114 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs @@ -1,6 +1,7 @@ -using System.Collections.Generic; -using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Collections.Generic; +using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab @@ -10,7 +11,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetPlaceholderForNameIfNotProvided(); - + var tabHeader = GetTabHeaderItem(context, output); var tabHeaderItems = context.GetValue>(TabItems); @@ -30,12 +31,28 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab if (!string.IsNullOrWhiteSpace(TagHelper.ParentDropdownName)) { - return "" + title + ""; + var anchor = new TagBuilder("a"); + anchor.AddCssClass("dropdown-item"); + anchor.Attributes.Add("id", id); + anchor.Attributes.Add("href", href); + anchor.InnerHtml.Append(title); + + return anchor.ToHtmlString(); } + else + { + var anchor = new TagBuilder("a"); + anchor.AddCssClass("nav-link " + AbpTabItemActivePlaceholder); + anchor.Attributes.Add("id", id); + anchor.Attributes.Add("href", href); + anchor.InnerHtml.Append(title); + + var listItem = new TagBuilder("li"); + listItem.AddCssClass("nav-item"); + listItem.InnerHtml.AppendHtml(anchor); - return "
  • " + - title + - "
  • "; + return listItem.ToHtmlString(); + } } protected virtual void SetPlaceholderForNameIfNotProvided() @@ -46,4 +63,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs index 2de18d0592..9080e49d83 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab @@ -34,16 +35,52 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab var attributes = GetTabHeaderAttributes(context, output); var classAttributesAsString = attributes.Where(a=>a.Name == "class").ToList().Select(a=>a.Value).JoinAsString(" "); - var otherAttributesAsString = attributes.Where(a => a.Name != "class").ToList().ToHtmlAttributesAsString(); + var otherAttributes = attributes.Where(a => a.Name != "class").ToList(); if (!string.IsNullOrWhiteSpace(TagHelper.ParentDropdownName)) { - return "" + title + ""; + var anchor = new TagBuilder("a"); + anchor.AddCssClass("dropdown-item " + classAttributesAsString); + anchor.Attributes.Add("id", id); + anchor.Attributes.Add("href", "#" + link); + anchor.Attributes.Add("data-toggle", "tab"); + anchor.Attributes.Add("role", "tab"); + anchor.Attributes.Add("aria-controls", control); + anchor.Attributes.Add("aria-selected", "false"); + + foreach (var attr in otherAttributes) + { + anchor.Attributes.Add(attr.Name, attr.Value.ToString()); + } + + anchor.InnerHtml.Append(title); + + return anchor.ToHtmlString(); + } + else + { + var anchor = new TagBuilder("a"); + anchor.AddCssClass("nav-link " + classAttributesAsString + " " + AbpTabItemActivePlaceholder); + anchor.Attributes.Add("id", id); + anchor.Attributes.Add("data-toggle", TabItemsDataTogglePlaceHolder); + anchor.Attributes.Add("href", "#" + link); + anchor.Attributes.Add("role", "tab"); + anchor.Attributes.Add("aria-controls", control); + anchor.Attributes.Add("aria-selected", AbpTabItemSelectedPlaceholder); + + foreach (var attr in otherAttributes) + { + anchor.Attributes.Add(attr.Name, attr.Value.ToString()); + } + + anchor.InnerHtml.Append(title); + + var listItem = new TagBuilder("li"); + listItem.AddCssClass("nav-item"); + listItem.InnerHtml.AppendHtml(anchor); + + return listItem.ToHtmlString(); } - - return "
  • " + - title + - "
  • "; } protected virtual string GetTabContentItem(TagHelperContext context, TagHelperOutput output, string content) @@ -53,11 +90,22 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab var attributes = GetTabContentAttributes(context, output); var classAttributesAsString = attributes.Where(a => a.Name == "class").ToList().Select(a => a.Name).JoinAsString(" "); - var otherAttributesAsString = attributes.Where(a => a.Name != "class").ToList().ToHtmlAttributesAsString(); + var otherAttributes = attributes.Where(a => a.Name != "class").ToList(); + + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("tab-pane fade " + classAttributesAsString + " " + AbpTabItemShowActivePlaceholder); + wrapper.Attributes.Add("id", id); + wrapper.Attributes.Add("role", "tabpanel"); + wrapper.Attributes.Add("aria-labelledby", headerId); + + foreach (var attr in otherAttributes) + { + wrapper.Attributes.Add(attr.Name, attr.Value.ToString()); + } + + wrapper.InnerHtml.AppendHtml(content); - return "
    " + - content + - "
    "; + return wrapper.ToHtmlString(); } protected virtual void SetPlaceholderForNameIfNotProvided() @@ -83,4 +131,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab .Select(a=> new TagHelperAttribute(a.Name.Substring(prefix.Length), a.Value)).ToList(); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs index a28e0c7057..92e50990a4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs @@ -1,9 +1,11 @@ -using System; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Razor.TagHelpers; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid; @@ -11,6 +13,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab { public class AbpTabsTagHelperService : AbpTagHelperService { + protected IHtmlGenerator HtmlGenerator { get; } + + public AbpTabsTagHelperService(IHtmlGenerator htmlGenerator) + { + HtmlGenerator = htmlGenerator; + } + public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { SetRandomNameIfNotProvided(); @@ -35,7 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab } } - + protected virtual string CombineHeadersAndContents(TagHelperContext context, TagHelperOutput output, string headers, string contents) { var combined = new StringBuilder(); @@ -61,31 +70,34 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab var navClass = TagHelper.TabStyle == TabStyle.Tab ? " nav-tabs" : " nav-pills"; var verticalClass = GetVerticalPillClassIfVertical(); - var surroundedHeaders = "
      " + Environment.NewLine + - headers + - "
    "; + var listElement = new TagBuilder("ul"); + listElement.AddCssClass("nav" + verticalClass + navClass); + listElement.Attributes.Add("id", id); + listElement.Attributes.Add("role", "tablist"); + listElement.InnerHtml.AppendHtml(headers); - return surroundedHeaders; + return listElement.ToHtmlString(); } protected virtual string SurroundContents(TagHelperContext context, TagHelperOutput output, string contents) { var id = TagHelper.Name + "Content"; - var surroundedContents = "
    " + Environment.NewLine + - contents + - "
    "; + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("tab-content"); + wrapper.Attributes.Add("id", id); + wrapper.InnerHtml.AppendHtml(contents); - return surroundedContents; + return wrapper.ToHtmlString(); } protected virtual string PlaceInsideColumn(string contents, int columnSize) { - var surroundedContents = "
    " + Environment.NewLine + - contents + - "
    "; + var wrapper = new TagBuilder("div"); + wrapper.AddCssClass("col-md-" + columnSize); + wrapper.InnerHtml.AppendHtml(contents); - return surroundedContents; + return wrapper.ToHtmlString(); } protected virtual void PlaceInsideRow(TagHelperOutput output) @@ -213,7 +225,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab protected virtual string SetTabItemNameIfNotProvided(string content, int index) { - return content.Replace(TabItemNamePlaceHolder, TagHelper.Name + "_" + index); + return content.Replace(TabItemNamePlaceHolder, HtmlGenerator.Encode(TagHelper.Name) + "_" + index); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/TagBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/TagBuilderExtensions.cs new file mode 100644 index 0000000000..cab43b963b --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/TagBuilderExtensions.cs @@ -0,0 +1,23 @@ +using System.IO; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers +{ + internal static class TagBuilderExtensions + { + public static string ToHtmlString(this TagBuilder tagBuilder) + { + return tagBuilder.ToHtmlString(HtmlEncoder.Default); + } + + public static string ToHtmlString(this TagBuilder tagBuilder, HtmlEncoder htmlEncoder) + { + using (var writer = new StringWriter()) + { + tagBuilder.WriteTo(writer, htmlEncoder); + return writer.ToString(); + } + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs index f95a0097cd..acef4a0951 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs @@ -1,6 +1,6 @@ -using System; -using System.Linq; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Razor.TagHelpers; +using System.Linq; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tooltip { @@ -24,12 +24,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tooltip var directory = GetDirectory() != TooltipDirectory.Default ? GetDirectory() : TooltipDirectory.Top; output.Attributes.Add("data-placement", directory.ToString().ToLowerInvariant()); - output.PreElement.SetHtmlContent( - "" + Environment.NewLine); + var span = new TagBuilder("span"); + span.AddCssClass("d-inline-block"); + span.Attributes.Add("tabindex", "0"); + span.Attributes.Add("data-toggle", "tooltip"); + span.Attributes.Add("data-placement", directory.ToString().ToLowerInvariant()); + span.Attributes.Add("title", GetTitle()); + + output.PreElement.SetHtmlContent(span.RenderStartTag()); - output.PostElement.SetHtmlContent(Environment.NewLine + ""); + output.PostElement.SetHtmlContent(span.RenderEndTag()); output.Attributes.Add("style", "pointer-events: none;"); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index f7defe4f79..2007980bc7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -27,6 +27,10 @@ } }; + var htmlEncode = function (html) { + return $('
    ').text(html).html(); + } + var _createDropdownItem = function (record, fieldItem, tableInstance) { var $li = $('
  • '); var $a = $(''); @@ -41,7 +45,7 @@ $a.append($("").addClass(fieldItem.iconClass + " mr-1")); } - $a.append(fieldItem.text); + $a.append(htmlEncode(fieldItem.text)); } if (fieldItem.action) { @@ -84,7 +88,7 @@ } else if (firstItem.iconClass) { $button.append($("").addClass(firstItem.iconClass + " mr-1")); } - $button.append(firstItem.text); + $button.append(htmlEncode(firstItem.text)); } if (firstItem.enabled && !firstItem.enabled({ record: record, table: tableInstance })) { @@ -128,9 +132,9 @@ } if (field.text) { - $dropdownButton.append(field.text); + $dropdownButton.append(htmlEncode(fieldItem.text)); } else { - $dropdownButton.append(localize("DatatableActionDropdownDefaultText")); + $dropdownButton.append(htmlEncode(localize("DatatableActionDropdownDefaultText"))); } $dropdownButton diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js index 44c2bdad27..9c99a20acd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js @@ -35,7 +35,12 @@ //change text if ($buttonInnerSpan.length && $button.attr('data-busy-text')) { $button.data('buttonOriginalText', $buttonInnerSpan.html()); - $buttonInnerSpan.html($button.attr('data-busy-text')); + + if ($button.data('busy-text-is-html')) { + $buttonInnerSpan.html($button.attr('data-busy-text')); + } else { + $buttonInnerSpan.text($button.attr('data-busy-text')); + } } $button.addClass('button-busy'); diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml index e58817d91c..c3aa9c0c92 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml @@ -295,6 +295,9 @@
  • busy-text: Sets "data-busy-text" attribute. Default value is localization of "ProcessingWithThreeDot" string.
  • +
  • + busy-text-is-html: Sets "data-busy-is-html" attribute. Default value is "false". +
  • \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml index 3763cd2601..4005b9d3d2 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml @@ -2,6 +2,11 @@ @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CarouselsModel @{ ViewData["Title"] = "Carousels"; + + var firstSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzEyIHRleHQgeyBmaWxsOiM0NDQ7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxMiI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM2NjYiPjwvcmVjdD48Zz48dGV4dCB4PSIyNDcuMjkxNjcxNzUyOTI5NyIgeT0iMjE4LjMiPkZpcnN0IHNsaWRlPC90ZXh0PjwvZz48L2c+PC9zdmc+"; + var secondSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzEyIHRleHQgeyBmaWxsOiM0NDQ7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxMiI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM2NjYiPjwvcmVjdD48Zz48dGV4dCB4PSIyNDcuMjkxNjcxNzUyOTI5NyIgeT0iMjE4LjMiPlNlY29uZCBzbGlkZTwvdGV4dD48L2c+PC9nPjwvc3ZnPg=="; + var thirdSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzE0IHRleHQgeyBmaWxsOiMzMzM7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxNCI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM1NTUiPjwvcmVjdD48Zz48dGV4dCB4PSIyNzYuOTc0OTk4NDc0MTIxMSIgeT0iMjE4LjMiPlRoaXJkIHNsaWRlPC90ZXh0PjwvZz48L2c+PC9zdmc+"; + } @section styles { @@ -31,11 +36,10 @@
    - - - - + + +
    @@ -76,9 +80,9 @@
    - - - + + +
    @@ -127,9 +131,9 @@
    - - - + + +
    @@ -183,7 +187,7 @@
    - +
    @@ -234,9 +238,9 @@
    - - - + + +