From 031d1058f8fdae95d35ed8fca2797f592dc944de Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 7 Jul 2024 14:42:25 +0200 Subject: [PATCH 01/59] 0.0.8-alpha --- README.md | 39 +++++++------------ .../WebExpress.WebUI.Test.csproj | 2 +- src/WebExpress.WebUI/WebControl/TypeIcon.cs | 2 + src/WebExpress.WebUI/WebExpress.WebUI.csproj | 14 +++---- .../WebFragment/FragmentItem.cs | 2 +- .../WebSettingPage/SettingPageManager.cs | 13 ------- 6 files changed, 24 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 29b79576..fa873627 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,40 @@ ![WebExpress](https://raw.githubusercontent.com/ReneSchwarzer/WebExpress/main/assets/banner.png) # WebExpress -WebExpress is a lightweight web server optimized for use in low-performance environments (e.g. Rasperry PI). By providing +`WebExpress` is a lightweight web server optimized for use in low-performance environments (e.g. Rasperry PI). By providing a powerful plugin system and a comprehensive API, web applications can be easily and quickly integrated into a .net -language (e.g. C#). Some advantages of WebExpress are: +language (e.g. C#). Some advantages of `WebExpress` are: - It is easy to use. - It offers a variety of features and tools that can help you build and manage your website. - It is fast and efficient and can help you save time and money. - It is flexible and can be customized to meet your specific requirements. -The WebExpress family includes the following projects: +The `WebExpress` family includes the following projects: -- [WebExpress](https://github.com/ReneSchwarzer/WebExpress#readme) - The web server for WebExpress applications and the documentation. -- [WebExpress.WebCore](https://github.com/ReneSchwarzer/WebExpress.WebCore#readme) - The core for WebExpress applications. -- [WebExpress.WebUI](https://github.com/ReneSchwarzer/WebExpress.WebUI#readme) - Common templates and controls for WebExpress applications. -- [WebExpress.WebIndex](https://github.com/ReneSchwarzer/WebExpress.WebIndex#readme) - Reverse index for WebExpress applications. -- [WebExpress.WebApp](https://github.com/ReneSchwarzer/WebExpress.WebApp#readme) - Business application template for WebExpress applications. +- [WebExpress](https://github.com/ReneSchwarzer/WebExpress#readme) - The web server for `WebExpress` applications and the documentation. +- [WebExpress.WebCore](https://github.com/ReneSchwarzer/WebExpress.WebCore#readme) - The core for `WebExpress` applications. +- [WebExpress.WebUI](https://github.com/ReneSchwarzer/WebExpress.WebUI#readme) - Common templates and controls for `WebExpress` applications. +- [WebExpress.WebIndex](https://github.com/ReneSchwarzer/WebExpress.WebIndex#readme) - Reverse index for `WebExpress` applications. +- [WebExpress.WebApp](https://github.com/ReneSchwarzer/WebExpress.WebApp#readme) - Business application template for `WebExpress` applications. # WebExpress.WebUI -WebExpress.WebUI is part of the WebExpress family. It provides templates and controls that standardize and facilitate the -creation of web pages. - -# Libraries used -- https://github.com/dotnet/core (MIT) -- https://getbootstrap.com/ (MIT) -- https://www.chartjs.org (MIT) -- https://jquery.com/ (MIT) -- https://summernote.org/ (MIT) -- https://popper.js.org/ (MIT) -- https://github.com/kurtobando/simple-tags (MIT) -- https://github.com/uxsolutions/bootstrap-datepicker (Apache 2.0) -- https://github.com/xoofx/markdig (BSD-2-Clause license) +`WebExpress.WebUI` is part of the WebExpress family. It provides templates and controls that standardize and facilitate the creation of web pages. # Download The current binaries are available for download [here](https://github.com/ReneSchwarzer/WebExpress/releases). # Start -To get started with WebExpress, use the following links and tutorials. +If you're looking to get started with `WebExpress`, we would recommend using the following documentation. It can help you understand the platform. - [installation guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/installation_guide.md) - [development guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/development_guide.md) -## Tutorials +# Learning +The following tutorials illustrate the essential techniques of `WebExpress`. These tutorials are designed to assist you, as a developer, in understanding the various aspects of `WebExpress`. Each tutorial provides a detailed, step-by-step guide that you can work through using an example. If you’re interested in beginning the development of `WebExpress` components, we would recommend you to complete some of these tutorials. + - [HelloWorld](https://github.com/ReneSchwarzer/WebExpress.Tutorial.HelloWorld#readme) +- [WebApp](https://github.com/ReneSchwarzer/WebExpress.Tutorial.WebApp#readme) # Tags -#NETCore #WebExpress #Controls #Templates +#WebUI #WebExpress #DotNet #NETCore diff --git a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj index 05a0080c..ba2cae01 100644 --- a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj +++ b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj @@ -12,7 +12,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/WebExpress.WebUI/WebControl/TypeIcon.cs b/src/WebExpress.WebUI/WebControl/TypeIcon.cs index 8e834094..499971b8 100644 --- a/src/WebExpress.WebUI/WebControl/TypeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/TypeIcon.cs @@ -60,6 +60,7 @@ public enum TypeIcon FolderOpen, Font, Forward, + Globe, GraduationCap, Hashtag, Hdd, @@ -181,6 +182,7 @@ public static string ToClass(this TypeIcon icon) TypeIcon.FolderOpen => "fas fa-folder-open", TypeIcon.Font => "fas fa-font", TypeIcon.Forward => "fas fa-forward", + TypeIcon.Globe => "fas fa-globe", TypeIcon.GraduationCap => "fas fa-graduation-cap", TypeIcon.Hashtag => "fas fa-hashtag", TypeIcon.Hdd => "fas fa-hdd", diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index 90ea4776..fadd2764 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -3,8 +3,8 @@ Library WebExpress.WebUI - 0.0.7.0 - 0.0.7.0 + 0.0.8.0 + 0.0.8.0 net8.0 any https://github.com/ReneSchwarzer/WebExpress.WebUI @@ -14,7 +14,7 @@ true True Provide user interface elements to the WebExpress web server. - 0.0.7-alpha + 0.0.8-alpha https://github.com/ReneSchwarzer/WebExpress icon.png README.md @@ -390,12 +390,8 @@ - - - - - - + + diff --git a/src/WebExpress.WebUI/WebFragment/FragmentItem.cs b/src/WebExpress.WebUI/WebFragment/FragmentItem.cs index c80cdb6e..8c6663c2 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentItem.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentItem.cs @@ -1,9 +1,9 @@ ο»Ώusing System; using System.Collections.Generic; using System.Linq; -using WebExpress.WebCore; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebCondition; +using WebExpress.WebCore.WebLog; using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPlugin; diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs index 060e7166..fa96b250 100644 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs +++ b/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs @@ -270,19 +270,6 @@ public void PrepareForLog(IPluginContext pluginContext, IList output, in string.Empty.PadRight(deep) + InternationalizationManager.I18N("webexpress.webui:settingpagemanager.titel") ); - - //foreach (var fragmentItem in GetFragmentItems(pluginContext)) - //{ - // output.Add - // ( - // string.Empty.PadRight(deep + 2) + - // InternationalizationManager.I18N - // ( - // "webexpress.webui:settingpagemanager.settingpage", - // fragmentItem.FragmentClass.Name - // ) - // ); - //} } } } \ No newline at end of file From 4d9e3b7c66a1a01c01797d80e5c6b917d5ef5e52 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 7 Jul 2024 22:50:55 +0200 Subject: [PATCH 02/59] change list control --- .../WebControl/ControlList.cs | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index fc284c6f..b7cb09f1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -5,6 +5,9 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a control list that can contain multiple control list items. + /// public class ControlList : Control { /// @@ -66,17 +69,17 @@ public ControlList(params ControlListItem[] items) /// /// The id of the control. /// The list entries. - public ControlList(string id, List items) + public ControlList(string id, IEnumerable items) : base(id) { - Items = items; + Items.AddRange(items); } /// /// Constructor /// /// The list entries. - public ControlList(List items) + public ControlList(IEnumerable items) : this(null, items) { } @@ -86,7 +89,6 @@ public ControlList(List items) /// private void Init() { - Items = new List(); ShowBorder = true; } @@ -115,18 +117,28 @@ public void Add(ControlListItem item) /// The control as html. public override IHtmlNode Render(RenderContext context) { - var items = Items.Where(x => x.Enable).Select(x => x.Render(context)).ToList(); + return Render(context, Items); + } + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The list entries. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, IEnumerable items) + { + var li = items.Where(x => x.Enable).Select(x => x.Render(context)).ToList(); switch (Layout) { case TypeLayoutList.Horizontal: case TypeLayoutList.Flush: case TypeLayoutList.Group: - items.ForEach(x => x.AddClass("list-group-item")); + li.ForEach(x => x.AddClass("list-group-item")); break; } - var html = new HtmlElementTextContentUl(items) + var html = new HtmlElementTextContentUl(li) { Id = Id, Class = Css.Concatenate("", GetClasses()), From c1d6e760b8d4a89d1f67100148e6ab46d94531ff Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 7 Jul 2024 23:31:21 +0200 Subject: [PATCH 03/59] changing form control --- .../WebControl/ControlForm.cs | 34 ++++++++++++++----- .../WebControl/ControlFormInline.cs | 29 +++++++++++++--- .../WebControl/IControlForm.cs | 22 +++++++++--- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index 79cde17e..4a10bc00 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -90,9 +90,19 @@ public class ControlForm : Control, IControlForm }; /// - /// Returns or sets the form items. + /// Returns or sets the request method. /// - public IList Items { get; } = new List(); + public RequestMethod Method { get; set; } = RequestMethod.POST; + + /// + /// Returns the form items. + /// + protected List _Items { get; } = new List(); + + /// + /// Returns the form items. + /// + public IEnumerable Items => _Items; /// /// Constructor @@ -113,10 +123,7 @@ public ControlForm(string id = null) public ControlForm(string id, params ControlFormItem[] items) : this(id) { - if (items != null) - { - (Items as List).AddRange(items); - } + _Items.AddRange(items); } /// @@ -300,7 +307,7 @@ public override IHtmlNode Render(RenderContext context) Style = GetStyles(), Role = Role, Action = Uri?.ToString() ?? renderContext.Uri?.ToString(), - Method = RequestMethod.POST.ToString(), + Method = Method.ToString(), Enctype = TypeEnctype.None }; @@ -371,7 +378,7 @@ public override IHtmlNode Render(RenderContext context) form.Elements.AddRange(renderContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); - context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{RequestMethod.POST.ToString()}');"); + context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{Method.ToString()}');"); return form; } @@ -382,7 +389,16 @@ public override IHtmlNode Render(RenderContext context) /// The form item. public void Add(params ControlFormItem[] item) { - (Items as List).AddRange(item); + _Items.AddRange(item); + } + + /// + /// Removes a form control item from the form. + /// + /// The form item. + public void Remove(ControlFormItem formItem) + { + _Items.Remove(formItem); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs index 573bdfc5..59bb9118 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs @@ -66,9 +66,19 @@ public class ControlFormInline : Control, IControlForm public ParameterScope Scope { get; set; } /// - /// Returns or sets the form items. + /// Returns or sets the request method. /// - public IList Items { get; } = new List(); + public RequestMethod Method { get; set; } = RequestMethod.POST; + + /// + /// Returns the form items. + /// + protected List _Items { get; } = new List(); + + /// + /// Returns the form items. + /// + public IEnumerable Items => _Items; /// /// Returns the validation results. @@ -103,7 +113,7 @@ public ControlFormInline(string id = null) public ControlFormInline(string id, params ControlFormItem[] items) : this(id) { - (Items as List).AddRange(items); + _Items.AddRange(items); } @@ -190,7 +200,7 @@ public override IHtmlNode Render(RenderContext context) Role = Role, Name = formName.ToLower(), Action = Uri?.ToString(), - Method = "post", + Method = Method.ToString(), Enctype = TypeEnctype.None }; @@ -253,7 +263,16 @@ public override IHtmlNode Render(RenderContext context) /// The form item. public void Add(params ControlFormItem[] item) { - (Items as List).AddRange(item); + _Items.AddRange(item); + } + + /// + /// Removes a form control item from the form. + /// + /// The form item. + public void Remove(ControlFormItem formItem) + { + _Items.Remove(formItem); } /// diff --git a/src/WebExpress.WebUI/WebControl/IControlForm.cs b/src/WebExpress.WebUI/WebControl/IControlForm.cs index ddb614b7..b18bead9 100644 --- a/src/WebExpress.WebUI/WebControl/IControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/IControlForm.cs @@ -1,5 +1,6 @@ ο»Ώusing System; using System.Collections.Generic; +using WebExpress.WebCore.WebMessage; namespace WebExpress.WebUI.WebControl { @@ -53,7 +54,12 @@ public interface IControlForm : IControl /// /// Returns or sets the form items. /// - IList Items { get; } + IEnumerable Items { get; } + + /// + /// Returns or sets the request method. + /// + RequestMethod Method { get; set; } /// /// Initializes the form. @@ -62,19 +68,25 @@ public interface IControlForm : IControl void Initialize(RenderContextFormular context); /// - /// Vorverarbeitung des Formulars + /// Pre-processes the form. /// /// The context in which the control is rendered. void PreProcess(RenderContextFormular context); /// - /// FΓΌgt Formularsteuerelement dem Formular hinzu + /// Adds form control items to the form. /// - /// Die Formularelemente + /// The form items. void Add(params ControlFormItem[] item); /// - /// PrΓΌft die Eingabeelemente auf Korrektheit der Daten + /// Removes a form control item from the form. + /// + /// The form item. + void Remove(ControlFormItem formItem); + + /// + /// Validates the input elements for correctness of the data. /// /// The context in which the inputs are validated. /// True if all form items are valid, false otherwise. From 9b4c79615c41b9498dd1b10d31de087e2fe518b0 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Mon, 8 Jul 2024 21:41:27 +0200 Subject: [PATCH 04/59] add tests --- .../Control/UnitTestControlList.cs | 48 +++++++++++++++++++ .../IHtmlNodeExtensions.cs | 22 +++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs create mode 100644 src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs new file mode 100644 index 00000000..7e69154d --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs @@ -0,0 +1,48 @@ +ο»Ώusing System.Globalization; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the list control. + /// + public class UnitTestControlList + { + /// + /// Tests a empty list. + /// + [Fact] + public void EmptyList() + { + var context = new WebCore.WebPage.RenderContext(); + var control = new ControlList(); + + Assert.Equal("
    ", control.Render(context).Trim()); + } + + /// + /// Tests a empty list. + /// + [Fact] + public void EmptyListGroup() + { + var context = new WebCore.WebPage.RenderContext(); + var control = new ControlList() { Layout = TypeLayoutList.Group }; + + Assert.Equal("
      ", control.Render(context).Trim()); + } + + /// + /// Tests a list. + /// + [Fact] + public void SimpleList() + { + var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var item = new ControlListItem(new ControlText() { Text = "abc" }); + var control = new ControlList(item); + + Assert.Equal("
      • abc
      ", control.Render(context).Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs new file mode 100644 index 00000000..6fa71bc2 --- /dev/null +++ b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs @@ -0,0 +1,22 @@ +ο»Ώusing System.Text.RegularExpressions; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.Test +{ + internal static class IHtmlNodeExtensions + { + /// + /// Removes extra spaces and line breaks from the input node. + /// + /// The node to clean. + /// A string with all consecutive spaces and line breaks reduced to single ones. + public static string Trim(this IHtmlNode node) + { + string withoutExtraSpaces = Regex.Replace(node.ToString().Trim(), @"\s+", " "); + string withoutExtraLineBreaks = Regex.Replace(withoutExtraSpaces, @"[\r\n]+", "\n"); + string withoutSpacesBetweenBrackets = Regex.Replace(withoutExtraLineBreaks, @">\s+<", "><"); + + return withoutSpacesBetweenBrackets; + } + } +} From 5aff101f4f7f21edc67176a95099c332e827b8e9 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Mon, 8 Jul 2024 22:56:04 +0200 Subject: [PATCH 05/59] quality improvements --- .../WebControl/ControlForm.cs | 33 ++- .../WebControl/ControlFormInline.cs | 225 ++++++++++-------- .../WebControl/ControlModalFormular.cs | 43 +++- 3 files changed, 185 insertions(+), 116 deletions(-) diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index 4a10bc00..54caeeda 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -245,12 +245,34 @@ public virtual void Process(RenderContextFormular context) /// The context in which the control is rendered. /// The control as html. public override IHtmlNode Render(RenderContext context) + { + return Render(context, Items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) + { + return Render(context, items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, IEnumerable items) { var renderContext = new RenderContextFormular(context, this); var fill = false; var process = false; - // PrΓΌfe ob und wie das Formular abgeschickt wurde + // check if and how the form was submitted if (context.Request.GetParameter("formular-id")?.Value == Id && context.Request.HasParameter("formular-submit-type")) { var value = context.Request.GetParameter("formular-submit-type")?.Value; @@ -278,7 +300,10 @@ public override IHtmlNode Render(RenderContext context) // initialization Initialize(renderContext); - (Items as List).ForEach(x => x?.Initialize(renderContext)); + foreach (var item in items) + { + item.Initialize(renderContext); + } OnInitialize(renderContext); SubmitButton.Initialize(renderContext); @@ -346,7 +371,7 @@ public override IHtmlNode Render(RenderContext context) }.Render(renderContext)); } - foreach (var item in Items.Where(x => x is ControlFormItemInputHidden)) + foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) { form.Elements.Add(item.Render(renderContext)); } @@ -362,7 +387,7 @@ public override IHtmlNode Render(RenderContext context) _ => new ControlFormItemGroupVertical(), }; - foreach (var item in Items.Where(x => x is not ControlFormItemInputHidden)) + foreach (var item in items.Where(x => x is not ControlFormItemInputHidden)) { group.Items.Add(item); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs index 59bb9118..aacfe660 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs @@ -138,6 +138,106 @@ public virtual void Initialize(RenderContextFormular context) } } + /// + /// Adds a form element. + /// + /// The form item. + public void Add(params ControlFormItem[] item) + { + _Items.AddRange(item); + } + + /// + /// Removes a form control item from the form. + /// + /// The form item. + public void Remove(ControlFormItem formItem) + { + _Items.Remove(formItem); + } + + /// + /// Raises the process event. + /// + /// The context in which the control is rendered. + protected virtual void OnProcess(RenderContextFormular context) + { + ProcessFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + } + + /// + /// Raises the process event. + /// + /// The context in which the control is rendered. + protected virtual void OnProcessAndNextFormular(RenderContextFormular context) + { + ProcessAndNextFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + } + + /// + /// Raises the store event. + /// + /// The context in which the control is rendered. + protected virtual void OnInitialize(RenderContextFormular context) + { + InitializeFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + } + + /// + /// Raises the data delivery event. + /// + /// The context in which the control is rendered. + protected virtual void OnFill(RenderContextFormular context) + { + FillFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + } + + /// + /// Raises the validation event. + /// + /// The event argument. + protected virtual void OnValidation(ValidationEventArgs e) + { + Validation?.Invoke(this, e); + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + /// True if all form items are valid, false otherwise. + public virtual bool Validate(RenderContextFormular context) + { + var valid = true; + var validationResults = ValidationResults as List; + + validationResults.Clear(); + + foreach (var v in Items.Where(x => x is IFormularValidation).Select(x => x as IFormularValidation)) + { + v.Validate(context); + + if (v.ValidationResult == TypesInputValidity.Error) + { + valid = false; + } + + validationResults.AddRange(v.ValidationResults); + } + + var args = new ValidationEventArgs() { Value = null, Context = context }; + OnValidation(args); + + validationResults.AddRange(args.Results); + + if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) + { + valid = false; + } + + return valid; + } + /// /// Vorverarbeitung des Formulars /// @@ -153,6 +253,28 @@ public virtual void PreProcess(RenderContextFormular context) /// The context in which the control is rendered. /// The control as html. public override IHtmlNode Render(RenderContext context) + { + return Render(context, Items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) + { + return Render(context, items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, IEnumerable items) { var renderContext = new RenderContextFormular(context, this); var formName = Name != null ? Name.StartsWith("formular") ? Name : $"formular_{Name}" : "formular"; @@ -206,7 +328,7 @@ public override IHtmlNode Render(RenderContext context) html.Elements.Add(new ControlFormItemInputHidden() { Name = "formular-id", Value = Id }.Render(renderContext)); - foreach (var item in Items) + foreach (var item in items) { if (item is ControlFormItemInput input) { @@ -256,106 +378,5 @@ public override IHtmlNode Render(RenderContext context) return html; } - - /// - /// Adds a form element. - /// - /// The form item. - public void Add(params ControlFormItem[] item) - { - _Items.AddRange(item); - } - - /// - /// Removes a form control item from the form. - /// - /// The form item. - public void Remove(ControlFormItem formItem) - { - _Items.Remove(formItem); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcess(RenderContextFormular context) - { - ProcessFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcessAndNextFormular(RenderContextFormular context) - { - ProcessAndNextFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the store event. - /// - /// The context in which the control is rendered. - protected virtual void OnInitialize(RenderContextFormular context) - { - InitializeFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the data delivery event. - /// - /// The context in which the control is rendered. - protected virtual void OnFill(RenderContextFormular context) - { - FillFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the validation event. - /// - /// The event argument. - protected virtual void OnValidation(ValidationEventArgs e) - { - Validation?.Invoke(this, e); - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - /// True if all form items are valid, false otherwise. - public virtual bool Validate(RenderContextFormular context) - { - var valid = true; - var validationResults = ValidationResults as List; - - validationResults.Clear(); - - foreach (var v in Items.Where(x => x is IFormularValidation).Select(x => x as IFormularValidation)) - { - v.Validate(context); - - if (v.ValidationResult == TypesInputValidity.Error) - { - valid = false; - } - - validationResults.AddRange(v.ValidationResults); - } - - var args = new ValidationEventArgs() { Value = null, Context = context }; - OnValidation(args); - - validationResults.AddRange(args.Results); - - if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - valid = false; - } - - return valid; - } - } } diff --git a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs b/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs index 79176eb8..5220944a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs @@ -1,4 +1,5 @@ -ο»Ώusing System.Linq; +ο»Ώusing System.Collections.Generic; +using System.Linq; using WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebPage; using static WebExpress.WebCore.Internationalization.InternationalizationManager; @@ -59,6 +60,15 @@ public ControlModalFormular(string id, string header, params ControlFormItem[] c Formular.Validated += OnValidatedFormular; } + /// + /// Adds a form control. + /// + /// The form item. + public void Add(params ControlFormItem[] item) + { + Formular.Add(item); + } + /// /// Invoked when the form is initialized. /// @@ -89,6 +99,28 @@ private void OnValidatedFormular(object sender, ValidationResultEventArgs e) /// The context in which the control is rendered. /// The control as html. public override IHtmlNode Render(RenderContext context) + { + return Render(context, Formular.Items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) + { + return Render(context, items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The formular items. + /// The control as html. + public virtual IHtmlNode Render(RenderContext context, IEnumerable items) { var fade = Fade; var classes = Classes.ToList(); @@ -196,14 +228,5 @@ public override IHtmlNode Render(RenderContext context) return form; } - - /// - /// FΓΌgt eine Formularsteuerelement hinzu - /// - /// The form item. - public void Add(params ControlFormItem[] item) - { - Formular.Add(item); - } } } From d4bb585d361c12042c95078ce786824937363461 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Tue, 9 Jul 2024 21:20:34 +0200 Subject: [PATCH 06/59] bug fixing --- .../Control/UnitTestControlAlert.cs | 81 +++++++++ .../Control/UnitTestControlFormular.cs | 140 ++++++++++++++++ .../Control/UnitTestControlFormularInline.cs | 140 ++++++++++++++++ .../Control/UnitTestControlList.cs | 68 +++++++- .../Control/UnitTestControlModalFormular.cs | 155 ++++++++++++++++++ .../Fixture/UnitTestControlFixture.cs | 82 +++++++++ src/WebExpress.WebUI.Test/TestPage.cs | 93 +++++++++++ .../WebExpress.WebUI.Test.csproj | 2 +- .../WebControl/ControlForm.cs | 11 -- .../WebControl/ControlFormInline.cs | 11 -- .../WebControl/ControlModalFormular.cs | 28 ++-- 11 files changed, 771 insertions(+), 40 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs create mode 100644 src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs create mode 100644 src/WebExpress.WebUI.Test/TestPage.cs diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs new file mode 100644 index 00000000..f63132a7 --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs @@ -0,0 +1,81 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the alert control. + /// + public class UnitTestControlAlert : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlAlert(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty alert. + /// + [Fact] + public void EmptyAlert() + { + // preconditions + var context = new WebCore.WebPage.RenderContext(); + var control = new ControlAlert(); + + // test execution + var html = control.Render(context); + + Assert.Equal(@"
      ", html.Trim()); + } + + /// + /// Tests a alert. + /// + [Fact] + public void AlertWithId() + { + // preconditions + var context = new WebCore.WebPage.RenderContext(); + var control = new ControlAlert("alertid"); + + // test execution + var html = control.Render(context); + + Assert.Contains(@"alertid", html.Trim()); + } + + /// + /// Tests a alert. + /// + [Fact] + public void AlertWithText() + { + // preconditions + var context = new WebCore.WebPage.RenderContext(); + var control = new ControlAlert() { Text = "abc" }; + + // test execution + var html = control.Render(context); + + Assert.Contains(@"abc", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs new file mode 100644 index 00000000..385db1b0 --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs @@ -0,0 +1,140 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the formular control. + /// + public class UnitTestControlFormular : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlFormular(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlForm(); + + var html = control.Render(context); + + // test execution + Assert.StartsWith("
      + /// Tests a simple form with id. + ///
      + [Fact] + public void EmptyFormWithId() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlForm("form"); + + var html = control.Render(context); + + // test execution + Assert.StartsWith(@" + /// Tests a simple form. + /// The control elements are added during rendering. + ///
      + [Fact] + public void SimpleFormAtRender() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlForm(); + var item = new ControlFormItemInputTextBox() { }; + + // test execution + var html = control.Render(context, [item]); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlForm("form", item); + + // test execution + var html = control.Render(context); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlForm("form"); + + control.Add(item); + + // test execution + var html = control.Render(context); + var str = html.ToString(); + + Assert.Contains(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs new file mode 100644 index 00000000..b0c835d1 --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs @@ -0,0 +1,140 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the inline formular control. + /// + public class UnitTestControlFormularInline : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlFormularInline(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlFormInline(); + + var html = control.Render(context); + + // test execution + Assert.StartsWith(@" + /// Tests a empty form. + ///
      + [Fact] + public void EmptyFormChangeSubmitText() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlFormInline(); + control.SubmitButton.Text = "sendbutton"; + + var html = control.Render(context); + var str = html.ToString(); + + // test execution + Assert.Contains(@"sendbutton", html.Trim()); + } + + /// + /// Tests a simple form with id. + /// + [Fact] + public void EmptyFormWithId() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlFormInline("form"); + + var html = control.Render(context); + + // test execution + Assert.StartsWith(@" + /// Tests a simple form. + /// The control elements are added during rendering. + ///
      + [Fact] + public void SimpleFormAtRender() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlFormInline(); + var item = new ControlFormItemInputTextBox() { }; + + // test execution + var html = control.Render(context, [item]); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlFormInline("form", item); + + // test execution + var html = control.Render(context); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlFormInline("form"); + + control.Add(item); + + // test execution + var html = control.Render(context); + var str = html.ToString(); + + Assert.Contains(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs index 7e69154d..6fddb8c5 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs @@ -1,22 +1,47 @@ ο»Ώusing System.Globalization; +using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; namespace WebExpress.WebUI.Test.Control { /// /// Tests the list control. /// - public class UnitTestControlList + public class UnitTestControlList : IClassFixture { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlList(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + /// /// Tests a empty list. /// [Fact] public void EmptyList() { + // preconditions var context = new WebCore.WebPage.RenderContext(); var control = new ControlList(); + // test execution Assert.Equal("
        ", control.Render(context).Trim()); } @@ -26,22 +51,61 @@ public void EmptyList() [Fact] public void EmptyListGroup() { + // preconditions var context = new WebCore.WebPage.RenderContext(); var control = new ControlList() { Layout = TypeLayoutList.Group }; + // test execution Assert.Equal("
          ", control.Render(context).Trim()); } /// /// Tests a list. + /// The list elements are added during rendering. /// [Fact] - public void SimpleList() + public void SimpleListAtRender() { + // preconditions + var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var item = new ControlListItem(new ControlText() { Text = "abc" }); + var control = new ControlList(); + + // test execution + Assert.Equal("
          • abc
          ", control.Render(context, [item]).Trim()); + } + + /// + /// Tests a list. + /// The list elements are added using add. + /// + [Fact] + public void SimpleListAtInstancing() + { + // preconditions var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; var item = new ControlListItem(new ControlText() { Text = "abc" }); var control = new ControlList(item); + // test execution + Assert.Equal("
          • abc
          ", control.Render(context).Trim()); + } + + /// + /// Tests a list. + /// The list elements are added using add. + /// + [Fact] + public void SimpleListAtAdd() + { + // preconditions + var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var item = new ControlListItem(new ControlText() { Text = "abc" }); + var control = new ControlList(); + + control.Add(item); + + // test execution Assert.Equal("
          • abc
          ", control.Render(context).Trim()); } } diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs new file mode 100644 index 00000000..fe942893 --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs @@ -0,0 +1,155 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the modal formular control. + /// + public class UnitTestControlModalFormular : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlModalFormular(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlModalFormular(); + + var html = control.Render(context); + var str = html.ToString(); + + // test execution + Assert.StartsWith(" + /// Tests a simple form with header. + ///
          + [Fact] + public void EmptyFormWithHeaderAtInstancing() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlModalFormular("form", "header"); + + var html = control.Render(context); + + // test execution + Assert.Contains(@"

          header

          ", html.Trim()); + } + + /// + /// Tests a simple form with header. + /// + [Fact] + public void EmptyFormWithHeaderAtProperty() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlModalFormular("form") { Header = "header" }; + + var html = control.Render(context); + + // test execution + Assert.Contains(@"

          header

          ", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added during rendering. + /// + [Fact] + public void SimpleFormAtRender() + { + // preconditions + var context = Fixture.CrerateContext(); + var control = new ControlModalFormular(); + var item = new ControlFormItemInputTextBox() { }; + + // test execution + var html = control.Render(context, [item]); + //var str = html.ToString(); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlModalFormular("form", item); + + // test execution + var html = control.Render(context); + + Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + // preconditions + var context = Fixture.CrerateContext(); + var item = new ControlFormItemInputTextBox() { }; + var control = new ControlModalFormular("form"); + + control.Add(item); + + // test execution + var html = control.Render(context); + + Assert.Contains(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs new file mode 100644 index 00000000..aa0c8d3a --- /dev/null +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -0,0 +1,82 @@ +ο»Ώusing Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using System.Net; +using System.Reflection; +using WebExpress.WebCore; +using WebExpress.WebCore.WebLog; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.Test.Fixture +{ + public class UnitTestControlFixture + { + /// + /// Create a fake render context; + /// + /// + public RenderContext CrerateContext() + { + var ctorRequestHeaderFields = typeof(RequestHeaderFields).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection)], null); + var ctorRequest = typeof(Request).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection), typeof(IHttpServerContext), typeof(RequestHeaderFields)], null); + var featureCollection = new FeatureCollection(); + + var requestFeature = new HttpRequestFeature + { + Headers = new HeaderDictionary + { + ["Host"] = "localhost", + ["Connection"] = "keep-alive", + ["ContentType"] = "text/html", + ["ContentLength"] = "0", + ["ContentLanguage"] = "en", + ["ContentEncoding"] = "gzip, deflate, br, zstd", + ["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + ["AcceptEncoding"] = "gzip, deflate, br, zstd", + ["AcceptLanguage"] = "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", + ["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0", + ["Referer"] = "0HN50661TV8TP" + } + }; + + var requestIdentifierFeature = new HttpRequestIdentifierFeature + { + TraceIdentifier = "Ihr TraceIdentifier-Wert" + }; + + var connectionFeature = new HttpConnectionFeature + { + LocalPort = 8080, + LocalIpAddress = IPAddress.Parse("192.168.0.1"), + RemotePort = 8080, + RemoteIpAddress = IPAddress.Parse("127.0.0.1"), + ConnectionId = "0HN50661TV8TP" + }; + + featureCollection.Set(requestFeature); + featureCollection.Set(requestIdentifierFeature); + featureCollection.Set(connectionFeature); + + var serverContext = new HttpServerContext + ( + "localhost", + [], + "", + "", + "", + "", + null, + null, + new Log() { LogMode = LogMode.Off }, + null + ); + var headers = (RequestHeaderFields)ctorRequestHeaderFields.Invoke([featureCollection]); + var request = (Request)ctorRequest.Invoke([featureCollection, serverContext, headers]); + var page = new TestPage(); + var visualTree = new VisualTreeControl(); + + return new WebCore.WebPage.RenderContext(page, request, visualTree); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestPage.cs b/src/WebExpress.WebUI.Test/TestPage.cs new file mode 100644 index 00000000..a625c8ba --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestPage.cs @@ -0,0 +1,93 @@ +ο»Ώusing System.Globalization; +using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebModule; +using WebExpress.WebCore.WebPage; +using WebExpress.WebCore.WebResource; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy class for testing purposes. + /// + public sealed class TestPage : IPage + { + /// + /// Returns or sets the title of the page. + /// + public string Title { get; set; } + + /// + /// Returns or sets the ID of the page. + /// + public string Id { get; set; } + + /// + /// Returns or sets the application context. + /// + public IApplicationContext ApplicationContext { get; set; } + + /// + /// Returns or sets the module context. + /// + public IModuleContext ModuleContext { get; set; } + + /// + /// Returns or sets the resource context. + /// + public IResourceContext ResourceContext { get; set; } + + /// + /// Returns or sets the culture information. + /// + public CultureInfo Culture { get => CultureInfo.CurrentCulture; set => throw new NotImplementedException(); } + + /// + /// Initializes the resource context. + /// + /// The resource context. + public void Initialization(IResourceContext resourceContext) + { + + } + + /// + /// Post-processes the request and response. + /// + /// The request. + /// The response. + /// The processed response. + public Response PostProcess(Request request, Response response) + { + return null; + } + + /// + /// Pre-processes the request. + /// + /// The request. + public void PreProcess(Request request) + { + + } + + /// + /// Processes the request. + /// + /// The request. + /// The processed response. + public Response Process(Request request) + { + return null; + } + + /// + /// Redirects to the specified URI. + /// + /// The URI to redirect to. + public void Redirecting(string uri) + { + + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj index ba2cae01..b74770e4 100644 --- a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj +++ b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj @@ -3,7 +3,7 @@ net8.0 enable - enable + disable false true diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index 54caeeda..deb20302 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -249,17 +249,6 @@ public override IHtmlNode Render(RenderContext context) return Render(context, Items); } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The formular items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) - { - return Render(context, items); - } - /// /// Convert to html. /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs index aacfe660..3fd08511 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs @@ -257,17 +257,6 @@ public override IHtmlNode Render(RenderContext context) return Render(context, Items); } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The formular items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) - { - return Render(context, items); - } - /// /// Convert to html. /// diff --git a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs b/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs index 5220944a..fb3b8d63 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs @@ -52,12 +52,12 @@ public ControlModalFormular(string id, params ControlFormItem[] content) /// The headline. /// The form controls. public ControlModalFormular(string id, string header, params ControlFormItem[] content) - : base("modal_" + id, string.Empty, content) + : base("modal_" + id, string.Empty, null) { - Formular = new ControlForm(id); + Formular = content != null ? new ControlForm(id, content) : new ControlForm(id); Formular.InitializeFormular += OnInitializeFormular; - Formular.Validated += OnValidatedFormular; + Header = header; } /// @@ -69,6 +69,15 @@ public void Add(params ControlFormItem[] item) Formular.Add(item); } + /// + /// Removes a form control. + /// + /// The form item. + public void Remove(ControlFormItem item) + { + Formular.Remove(item); + } + /// /// Invoked when the form is initialized. /// @@ -103,17 +112,6 @@ public override IHtmlNode Render(RenderContext context) return Render(context, Formular.Items); } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The formular items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, params ControlFormItem[] items) - { - return Render(context, items); - } - /// /// Convert to html. /// @@ -125,7 +123,7 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerable Date: Tue, 9 Jul 2024 23:46:19 +0200 Subject: [PATCH 07/59] add tests --- .../UnitTestControlFormItemInputRadio.cs | 97 +++++++++++++++++++ .../Fixture/UnitTestControlFixture.cs | 12 ++- .../IHtmlNodeExtensions.cs | 10 +- .../WebControl/ControlFormItemInputRadio.cs | 19 ---- 4 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs new file mode 100644 index 00000000..4f0bd01d --- /dev/null +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs @@ -0,0 +1,97 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.Control +{ + /// + /// Tests the inline radio control. + /// + public class UnitTestControlFormItemInputRadio : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Constructor + /// + /// The log. + /// The test context. + public UnitTestControlFormItemInputRadio(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty control. + /// + [Fact] + public void Empty() + { + // preconditions + var context = Fixture.CrerateContextFormular(); + var control = new ControlFormItemInputRadio(); + + var html = control.Render(context).Trim(); + + // test execution + Assert.StartsWith(@"
          ", html); + } + + /// + /// Tests a control. + /// + [Fact] + public void True() + { + // preconditions + var context = Fixture.CrerateContextFormular(); + var control = new ControlFormItemInputRadio() { Checked = true }; + + var html = control.Render(context).Trim(); + + // test execution + Assert.StartsWith(@"
          ", html); + } + + /// + /// Tests a control. + /// + [Fact] + public void False() + { + // preconditions + var context = Fixture.CrerateContextFormular(); + var control = new ControlFormItemInputRadio() { Checked = false }; + + var html = control.Render(context).Trim(); + + // test execution + Assert.StartsWith(@"
          ", html); + } + + /// + /// Tests a control. + /// + [Fact] + public void Description() + { + // preconditions + var context = Fixture.CrerateContextFormular(); + var control = new ControlFormItemInputRadio() { Description = "abcdefg" }; + + var html = control.Render(context).Trim(); + + // test execution + Assert.StartsWith(@"
          ", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index aa0c8d3a..171c2130 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -6,6 +6,7 @@ using WebExpress.WebCore.WebLog; using WebExpress.WebCore.WebMessage; using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebControl; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.Fixture @@ -15,7 +16,7 @@ public class UnitTestControlFixture /// /// Create a fake render context; /// - /// + /// A fake context for testing. public RenderContext CrerateContext() { var ctorRequestHeaderFields = typeof(RequestHeaderFields).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection)], null); @@ -78,5 +79,14 @@ public RenderContext CrerateContext() return new WebCore.WebPage.RenderContext(page, request, visualTree); } + + /// + /// Create a fake render formular context; + /// + /// A fake context for testing. + public RenderContextFormular CrerateContextFormular() + { + return new RenderContextFormular(CrerateContext(), new ControlForm()); + } } } diff --git a/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs index 6fa71bc2..6cff4fba 100644 --- a/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs +++ b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs @@ -12,11 +12,13 @@ internal static class IHtmlNodeExtensions /// A string with all consecutive spaces and line breaks reduced to single ones. public static string Trim(this IHtmlNode node) { - string withoutExtraSpaces = Regex.Replace(node.ToString().Trim(), @"\s+", " "); - string withoutExtraLineBreaks = Regex.Replace(withoutExtraSpaces, @"[\r\n]+", "\n"); - string withoutSpacesBetweenBrackets = Regex.Replace(withoutExtraLineBreaks, @">\s+<", "><"); + var withoutExtraLineBreaks = Regex.Replace(node.ToString().Trim(), @"[\r\n]+", ""); + var withoutExtraSpaces = Regex.Replace(withoutExtraLineBreaks, @"\s+", " "); + var withoutSpacesBetweenBrackets = Regex.Replace(withoutExtraSpaces, @">\s+<", "><"); + var withoutSpacesLeftBrackets = Regex.Replace(withoutSpacesBetweenBrackets, @"\s+<", "<"); + var withoutSpacesRightBrackets = Regex.Replace(withoutSpacesLeftBrackets, @">\s+", ">"); - return withoutSpacesBetweenBrackets; + return withoutSpacesRightBrackets; } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs index 25169534..68e64534 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs @@ -11,23 +11,6 @@ public class ControlFormItemInputRadio : ControlFormItemInput ///
          public string Option { get; set; } - ///// - ///// Returns or sets the value of the optiopn. - ///// - //public new string Value - //{ - // get => GetParam(Name); - // set - // { - // var v = GetParam(Name); - - // if (string.IsNullOrWhiteSpace(v)) - // { - // AddParam(Name, value, Formular.Scope); - // } - // } - //} - /// /// Liefert oder setzt ob die Checkbox in einer neuen Zeile angezeigt werden soll /// @@ -75,8 +58,6 @@ public ControlFormItemInputRadio(string id, string name) /// The context in which the control is rendered. public override void Initialize(RenderContextFormular context) { - //AddParam(name, Formular.Scope); - //Value = GetParam(Name); } /// From dc166c2ca0c35d57b0f54d7263a2494b958cb68e Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Wed, 10 Jul 2024 21:24:20 +0200 Subject: [PATCH 08/59] quality improvements --- .../Control/UnitTestControlFormularInline.cs | 1 + .../Assets/css/webexpress.webui.form.css | 5 +++++ src/WebExpress.WebUI/Module.cs | 16 ++++++++-------- .../WebFragment/FragmentManager.cs | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs index b0c835d1..c7d8c30b 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs @@ -41,6 +41,7 @@ public void EmptyForm() var control = new ControlFormInline(); var html = control.Render(context); + var str = html.ToString(); // test execution Assert.StartsWith(@" /// Constructor @@ -21,26 +21,26 @@ public Module() /// /// Instillation of the module. Here, for example, managed resources can be loaded. /// - /// The context that applies to the execution of the plugin. - public void Initialization(IModuleContext context) + /// The context that applies to the execution of the plugin. + public override void Initialization(IModuleContext moduleContext) { - + base.Initialization(moduleContext); } /// /// Invoked when the module starts working. The call is concurrent. /// - public void Run() + public override void Run() { - + base.Run(); } /// /// Release unmanaged resources that have been reserved during use. /// - public void Dispose() + public override void Dispose() { - + base.Dispose(); } } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs index a9a2e1a3..265d505d 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs @@ -373,7 +373,7 @@ public IEnumerable GetCacheableFragments IEnumerable scopes ) where T : IControl { - var applicationContext = page?.ApplicationContext; + var applicationContext = page?.ResourceContext.ApplicationContext; scopes ??= Enumerable.Empty(); var fragmentItems = GetFragmentItems($"{section}:") From f3f3eaac83b4d006ed720a001f47df5d5edb7768 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Thu, 11 Jul 2024 21:57:38 +0200 Subject: [PATCH 09/59] quality improvements --- src/WebExpress.WebUI/Plugin.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/WebExpress.WebUI/Plugin.cs b/src/WebExpress.WebUI/Plugin.cs index c2a3206b..42713697 100644 --- a/src/WebExpress.WebUI/Plugin.cs +++ b/src/WebExpress.WebUI/Plugin.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI [Name("webexpress.webui")] [Description("plugin.description")] [Icon("/assets/img/Logo.png")] - public sealed class Plugin : IPlugin + public sealed class Plugin : WebCore.WebPlugin.Plugin { /// /// Constructor @@ -21,24 +21,25 @@ public Plugin() /// Initialization of the plugin. Here, for example, managed resources can be loaded. /// /// The context of the plugin that applies to the execution of the plugin. - public void Initialization(IPluginContext context) + public override void Initialization(IPluginContext context) { + base.Initialization(context); } /// /// Called when the plugin starts working. Run is called concurrently. /// - public void Run() + public override void Run() { - + base.Run(); } /// /// Release of unmanaged resources reserved during use. /// - public void Dispose() + public override void Dispose() { - + base.Dispose(); } } } From 4ae49b6608ab6765ef90926d4d1ee27fa0e786cb Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Mon, 15 Jul 2024 18:32:11 +0200 Subject: [PATCH 10/59] quality improvements --- src/WebExpress.WebUI/WebControl/IControl.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/WebExpress.WebUI/WebControl/IControl.cs b/src/WebExpress.WebUI/WebControl/IControl.cs index e6af7033..805ddf95 100644 --- a/src/WebExpress.WebUI/WebControl/IControl.cs +++ b/src/WebExpress.WebUI/WebControl/IControl.cs @@ -1,5 +1,4 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; +ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebPage; namespace WebExpress.WebUI.WebControl @@ -7,20 +6,10 @@ namespace WebExpress.WebUI.WebControl public interface IControl { /// - /// Liefert Returns or sets the id. + /// Returns or sets the id. /// string Id { get; } - /// - /// Liefert oder setzt die Css-Klasse - /// - List Classes { get; set; } - - /// - /// Liefert oder setzt die Css-Style - /// - List Styles { get; set; } - /// /// Convert to html. /// From b1651cb8407f918b4be6b4ed01166f3a03994a23 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 11 Aug 2024 21:33:55 +0200 Subject: [PATCH 11/59] form refactoring --- .../Control/UnitTestControlAlert.cs | 2 +- ...trolFormular.cs => UnitTestControlForm.cs} | 37 +- ...Inline.cs => UnitTestControlFormInline.cs} | 22 +- .../UnitTestControlFormItemInputRadio.cs | 10 +- .../Control/UnitTestControlList.cs | 11 +- ...ormular.cs => UnitTestControlModalForm.cs} | 22 +- .../Data/ComplexForm.txt | 30 ++ .../Fixture/UnitTestControlFixture.cs | 100 ++++- src/WebExpress.WebUI.Test/TestApplication.cs | 37 ++ src/WebExpress.WebUI.Test/TestModule.cs | 40 ++ src/WebExpress.WebUI.Test/TestPage.cs | 30 +- src/WebExpress.WebUI.Test/TestPlugin.cs | 37 ++ .../WebExpress.WebUI.Test.csproj | 8 + .../WebFragment/FragmentHeaderPrimary.cs | 27 ++ ...lar.css => webexpress.webui.modalform.css} | 4 +- ...mular.js => webexpress.webui.modalform.js} | 6 +- src/WebExpress.WebUI/Module.cs | 2 +- src/WebExpress.WebUI/Plugin.cs | 2 +- .../WebAttribute/OptionAttribute.cs | 2 +- .../WebAttribute/OrderAttribute.cs | 2 +- .../WebAttribute/SectionAttribute.cs | 2 +- .../WebAttribute/SettingContextAttribute.cs | 2 +- .../WebAttribute/SettingGroupAttribute.cs | 2 +- .../WebAttribute/SettingHideAttribute.cs | 2 +- .../WebAttribute/SettingIconAttribute.cs | 4 +- .../WebAttribute/SettingSectionAttribute.cs | 2 +- src/WebExpress.WebUI/WebControl/Control.cs | 2 +- .../WebControl/ControlArlert.cs | 2 +- .../WebControl/ControlAttribute.cs | 2 +- .../WebControl/ControlAvatar.cs | 2 +- .../WebControl/ControlBadge.cs | 6 +- .../WebControl/ControlBreadcrumb.cs | 4 +- .../WebControl/ControlButton.cs | 6 +- .../WebControl/ControlButtonLink.cs | 8 +- .../WebControl/ControlCanvas.cs | 10 +- .../WebControl/ControlCardCounter.cs | 2 +- .../WebControl/ControlCarousel.cs | 4 +- .../WebControl/ControlCarouselItem.cs | 2 +- .../WebControl/ControlChart.cs | 2 +- .../WebControl/ControlChartDataset.cs | 2 +- .../WebControl/ControlDropdown.cs | 10 +- .../WebControl/ControlDropdownItemDivider.cs | 2 +- .../WebControl/ControlDropdownItemHeader.cs | 4 +- .../WebControl/ControlDropdownItemLink.cs | 8 +- .../WebControl/ControlForm.cs | 304 ++++++++++---- .../WebControl/ControlFormInline.cs | 371 ------------------ .../WebControl/ControlFormItem.cs | 8 +- .../WebControl/ControlFormItemButton.cs | 12 +- .../WebControl/ControlFormItemButtonSubmit.cs | 23 ++ .../WebControl/ControlFormItemGroup.cs | 16 +- .../WebControl/ControlFormItemGroupColumn.cs | 16 +- .../ControlFormItemGroupColumnHorizontal.cs | 16 +- .../ControlFormItemGroupColumnMix.cs | 16 +- .../ControlFormItemGroupColumnVertical.cs | 16 +- .../ControlFormItemGroupHorizontal.cs | 16 +- .../WebControl/ControlFormItemGroupMix.cs | 16 +- .../ControlFormItemGroupVertical.cs | 16 +- .../WebControl/ControlFormItemHelpText.cs | 8 +- .../WebControl/ControlFormItemInput.cs | 8 +- .../ControlFormItemInputCheckbox.cs | 8 +- .../ControlFormItemInputComboBox.cs | 14 +- .../ControlFormItemInputComboBoxItem.cs | 6 +- .../ControlFormItemInputDatepicker.cs | 8 +- .../WebControl/ControlFormItemInputFile.cs | 10 +- .../WebControl/ControlFormItemInputGroup.cs | 10 +- .../WebControl/ControlFormItemInputHidden.cs | 8 +- .../WebControl/ControlFormItemInputMove.cs | 26 +- .../WebControl/ControlFormItemInputRadio.cs | 10 +- .../ControlFormItemInputSelection.cs | 12 +- .../WebControl/ControlFormItemInputTextBox.cs | 10 +- .../WebControl/ControlFormItemLabel.cs | 18 +- .../WebControl/ControlFormItemPanel.cs | 8 +- .../WebControl/ControlFormItemPrepend.cs | 8 +- .../WebControl/ControlFormItemStaticText.cs | 6 +- .../WebControl/ControlHtml.cs | 4 +- .../WebControl/ControlIcon.cs | 2 +- .../WebControl/ControlImage.cs | 4 +- .../WebControl/ControlLine.cs | 2 +- .../WebControl/ControlLink.cs | 14 +- .../WebControl/ControlLinkList.cs | 2 +- .../WebControl/ControlList.cs | 10 +- .../WebControl/ControlListItem.cs | 10 +- .../WebControl/ControlListItemButton.cs | 10 +- .../WebControl/ControlListItemLink.cs | 10 +- .../WebControl/ControlModal.cs | 10 +- ...olModalFormular.cs => ControlModalForm.cs} | 56 ++- .../WebControl/ControlMultipleProgressBar.cs | 4 +- .../WebControl/ControlNavigation.cs | 8 +- .../ControlNavigationItemDropdown.cs | 2 +- .../WebControl/ControlNavigationItemHeader.cs | 4 +- .../WebControl/ControlNavigationItemLink.cs | 2 +- .../WebControl/ControlPagination.cs | 2 +- .../WebControl/ControlPanel.cs | 12 +- .../WebControl/ControlPanelCallout.cs | 6 +- .../WebControl/ControlPanelCard.cs | 12 +- .../WebControl/ControlPanelCenter.cs | 6 +- .../WebControl/ControlPanelDialog.cs | 2 +- .../WebControl/ControlPanelFilter.cs | 3 +- .../WebControl/ControlPanelFlexbox.cs | 10 +- .../WebControl/ControlPanelFooter.cs | 6 +- .../WebControl/ControlPanelGrid.cs | 2 +- .../WebControl/ControlPanelHeader.cs | 6 +- .../WebControl/ControlPanelMain.cs | 2 +- .../WebControl/ControlPanelMedia.cs | 4 +- .../WebControl/ControlPanelNavbar.cs | 6 +- .../WebControl/ControlPanelSplit.cs | 6 +- .../WebControl/ControlPanelToast.cs | 2 +- .../WebControl/ControlPanelTool.cs | 6 +- .../WebControl/ControlProgressBar.cs | 6 +- .../WebControl/ControlSplitButton.cs | 12 +- .../ControlSplitButtonItemDivider.cs | 2 +- .../ControlSplitButtonItemHeader.cs | 4 +- .../WebControl/ControlSplitButtonItemLink.cs | 2 +- .../WebControl/ControlSplitButtonLink.cs | 14 +- .../WebControl/ControlTable.cs | 2 +- .../WebControl/ControlTableColumn.cs | 2 +- .../WebControl/ControlTableRow.cs | 2 +- .../WebControl/ControlTableSortable.cs | 2 +- src/WebExpress.WebUI/WebControl/ControlTag.cs | 6 +- .../WebControl/ControlTagCloud.cs | 2 +- .../WebControl/ControlText.cs | 4 +- .../WebControl/ControlTimeline.cs | 4 +- .../WebControl/ControlTimelineComment.cs | 2 +- .../WebControl/ControlTimelineItem.cs | 13 +- .../WebControl/ControlToolbar.cs | 6 +- .../WebControl/ControlToolbarItemButton.cs | 2 +- .../WebControl/ControlToolbarItemSeperator.cs | 2 +- .../WebControl/ControlTree.cs | 10 +- .../WebControl/ControlTreeItem.cs | 10 +- .../WebControl/ControlTreeItemLink.cs | 10 +- .../WebControl/FormEventArgs.cs | 22 ++ .../WebControl/FormularEventArgs.cs | 22 -- .../WebControl/IControlForm.cs | 19 +- ...rmularValidation.cs => IFormValidation.cs} | 4 +- .../WebControl/PropertyBorder.cs | 8 +- .../WebControl/PropertyColor.cs | 2 +- .../WebControl/PropertyColorBackground.cs | 6 +- .../PropertyColorBackgroundAlert.cs | 4 +- .../PropertyColorBackgroundBadge.cs | 4 +- .../WebControl/PropertyColorBackgroundList.cs | 4 +- .../WebControl/PropertyColorBorder.cs | 4 +- .../WebControl/PropertyColorButton.cs | 4 +- .../WebControl/PropertyColorCallout.cs | 4 +- .../WebControl/PropertyColorChart.cs | 6 +- .../WebControl/PropertyColorLine.cs | 4 +- .../WebControl/PropertyColorNavbar.cs | 4 +- .../WebControl/PropertyColorProgress.cs | 4 +- .../WebControl/PropertyColorText.cs | 6 +- .../WebControl/PropertyGrid.cs | 4 +- .../WebControl/PropertyIcon.cs | 4 +- .../WebControl/PropertyMaxSizeIcon.cs | 4 +- .../WebControl/PropertyModal.cs | 8 +- .../WebControl/PropertyOnChange.cs | 4 +- .../WebControl/PropertyOnClick.cs | 2 +- .../WebControl/PropertySizeIcon.cs | 4 +- .../WebControl/PropertySizeText.cs | 4 +- .../WebControl/PropertySpacing.cs | 8 +- .../WebControl/PropertySpacingMargin.cs | 8 +- .../WebControl/PropertySpacingPadding.cs | 8 +- ...ontextFormular.cs => RenderContextForm.cs} | 24 +- ...ularGroup.cs => RenderContextFormGroup.cs} | 14 +- .../WebControl/TypeLayoutForm.cs | 7 +- .../WebControl/TypeLayoutFormItem.cs | 12 + src/WebExpress.WebUI/WebControl/TypeModal.cs | 2 +- .../WebControl/ValidationEventArgs.cs | 10 +- .../WebControl/ValidationResult.cs | 2 +- .../WebControl/ValidationResultEventArgs.cs | 12 +- src/WebExpress.WebUI/WebExpress.WebUI.csproj | 8 +- .../WebFragment/FragmentCacheItem.cs | 2 +- .../WebFragment/FragmentContext.cs | 2 +- .../WebFragment/FragmentControlButtonLink.cs | 2 +- .../FragmentControlDropdownItemLink.cs | 2 +- .../WebFragment/FragmentControlImage.cs | 2 +- .../WebFragment/FragmentControlLink.cs | 2 +- .../WebFragment/FragmentControlList.cs | 2 +- ...rInline.cs => FragmentControlModalForm.cs} | 8 +- .../FragmentControlModalFormular.cs | 32 -- .../FragmentControlNavigationItemLink.cs | 2 +- .../WebFragment/FragmentControlPanel.cs | 2 +- .../FragmentControlPanelFlexbox.cs | 2 +- .../WebFragment/FragmentControlPanelTool.cs | 2 +- .../FragmentControlSplitButtonItemLink.cs | 2 +- .../WebFragment/FragmentControlText.cs | 2 +- .../WebFragment/FragmentControlTree.cs | 2 +- .../WebFragment/FragmentManager.cs | 4 +- src/WebExpress.WebUI/WebPage/PageControl.cs | 6 +- .../WebPage/RenderContextControl.cs | 4 +- .../WebPage/VisualTreeControl.cs | 2 +- src/WebExpress.WebUI/WebResource/Asset.cs | 2 +- .../WebSection/SectionControl.cs | 38 ++ .../WebSettingPage/SettingPageManager.cs | 2 +- 191 files changed, 1206 insertions(+), 1113 deletions(-) rename src/WebExpress.WebUI.Test/Control/{UnitTestControlFormular.cs => UnitTestControlForm.cs} (71%) rename src/WebExpress.WebUI.Test/Control/{UnitTestControlFormularInline.cs => UnitTestControlFormInline.cs} (80%) rename src/WebExpress.WebUI.Test/Control/{UnitTestControlModalFormular.cs => UnitTestControlModalForm.cs} (85%) create mode 100644 src/WebExpress.WebUI.Test/Data/ComplexForm.txt create mode 100644 src/WebExpress.WebUI.Test/TestApplication.cs create mode 100644 src/WebExpress.WebUI.Test/TestModule.cs create mode 100644 src/WebExpress.WebUI.Test/TestPlugin.cs create mode 100644 src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs rename src/WebExpress.WebUI/Assets/css/{webexpress.webui.modalformular.css => webexpress.webui.modalform.css} (71%) rename src/WebExpress.WebUI/Assets/js/{webexpress.webui.modalformular.js => webexpress.webui.modalform.js} (94%) delete mode 100644 src/WebExpress.WebUI/WebControl/ControlFormInline.cs create mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs rename src/WebExpress.WebUI/WebControl/{ControlModalFormular.cs => ControlModalForm.cs} (76%) create mode 100644 src/WebExpress.WebUI/WebControl/FormEventArgs.cs delete mode 100644 src/WebExpress.WebUI/WebControl/FormularEventArgs.cs rename src/WebExpress.WebUI/WebControl/{IFormularValidation.cs => IFormValidation.cs} (88%) rename src/WebExpress.WebUI/WebControl/{RenderContextFormular.cs => RenderContextForm.cs} (71%) rename src/WebExpress.WebUI/WebControl/{RenderContextFormularGroup.cs => RenderContextFormGroup.cs} (60%) create mode 100644 src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs rename src/WebExpress.WebUI/WebFragment/{FragmentControlFormularInline.cs => FragmentControlModalForm.cs} (76%) delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentControlModalFormular.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionControl.cs diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs index f63132a7..3ee85bf9 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs @@ -20,7 +20,7 @@ public class UnitTestControlAlert : IClassFixture protected UnitTestControlFixture Fixture { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs similarity index 71% rename from src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs rename to src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs index 385db1b0..2e88deb9 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormular.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs @@ -5,9 +5,9 @@ namespace WebExpress.WebUI.Test.Control { /// - /// Tests the formular control. + /// Tests the form control. /// - public class UnitTestControlFormular : IClassFixture + public class UnitTestControlForm : IClassFixture { /// /// Returns the log. @@ -20,11 +20,11 @@ public class UnitTestControlFormular : IClassFixture protected UnitTestControlFixture Fixture { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. - public UnitTestControlFormular(UnitTestControlFixture fixture, ITestOutputHelper output) + public UnitTestControlForm(UnitTestControlFixture fixture, ITestOutputHelper output) { Fixture = fixture; Output = output; @@ -55,7 +55,7 @@ public void EmptyFormChangeSubmitText() // preconditions var context = Fixture.CrerateContext(); var control = new ControlForm(); - control.SubmitButton.Text = "sendbutton"; + control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); var html = control.Render(context); var str = html.ToString(); @@ -136,5 +136,32 @@ public void SimpleFormAtAdd() Assert.Contains(@"", html.Trim()); } + + /// + /// Tests a complex form. + /// + [Fact] + public void ComplexForm() + { + // preconditions + var expectedResult = Fixture.GetEmbeddedResource("ComplexForm.txt"); + var context = Fixture.CrerateContext(); + var item1 = new ControlFormItemInputTextBox() { Label = "Label1", Help = "Help1", Placeholder = "Placeholder1" }; + var item2 = new ControlFormItemInputTextBox() { Label = "Label2", Help = "Help2", Placeholder = "Placeholder2" }; + var submitButton = new ControlFormItemButtonSubmit("Submit"); + var control = new ControlForm("form", item1, item2); + control.AddPrimaryButton(submitButton); + + + // test execution + var html = control.Render(context); + var str = html.ToString(); + + // postconditions + expectedResult = expectedResult.Replace("05c888e8-15f3-4be8-b765-0d7be63cc82b", control.FormId.Id); + expectedResult = expectedResult.Replace("974c6159-98e3-4ede-8bb5-6bc4d52e1770", control.SubmitType.Id); + + Assert.Equal(expectedResult.Trim(), str.Trim()); + } } } diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs similarity index 80% rename from src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs rename to src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs index c7d8c30b..7598f96b 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormularInline.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs @@ -5,9 +5,9 @@ namespace WebExpress.WebUI.Test.Control { /// - /// Tests the inline formular control. + /// Tests the inline form control. /// - public class UnitTestControlFormularInline : IClassFixture + public class UnitTestControlFormInline : IClassFixture { /// /// Returns the log. @@ -20,11 +20,11 @@ public class UnitTestControlFormularInline : IClassFixture - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. - public UnitTestControlFormularInline(UnitTestControlFixture fixture, ITestOutputHelper output) + public UnitTestControlFormInline(UnitTestControlFixture fixture, ITestOutputHelper output) { Fixture = fixture; Output = output; @@ -38,7 +38,7 @@ public void EmptyForm() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlFormInline(); + var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; var html = control.Render(context); var str = html.ToString(); @@ -55,8 +55,8 @@ public void EmptyFormChangeSubmitText() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlFormInline(); - control.SubmitButton.Text = "sendbutton"; + var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; + control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); var html = control.Render(context); var str = html.ToString(); @@ -73,7 +73,7 @@ public void EmptyFormWithId() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlFormInline("form"); + var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; var html = control.Render(context); @@ -90,7 +90,7 @@ public void SimpleFormAtRender() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlFormInline(); + var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; var item = new ControlFormItemInputTextBox() { }; // test execution @@ -109,7 +109,7 @@ public void SimpleFormAtInstancing() // preconditions var context = Fixture.CrerateContext(); var item = new ControlFormItemInputTextBox() { }; - var control = new ControlFormInline("form", item); + var control = new ControlForm("form", item) { FormLayout = TypeLayoutForm.Inline }; // test execution var html = control.Render(context); @@ -127,7 +127,7 @@ public void SimpleFormAtAdd() // preconditions var context = Fixture.CrerateContext(); var item = new ControlFormItemInputTextBox() { }; - var control = new ControlFormInline("form"); + var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; control.Add(item); diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs index 4f0bd01d..2b66e790 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs @@ -20,7 +20,7 @@ public class UnitTestControlFormItemInputRadio : IClassFixture - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. @@ -37,7 +37,7 @@ public UnitTestControlFormItemInputRadio(UnitTestControlFixture fixture, ITestOu public void Empty() { // preconditions - var context = Fixture.CrerateContextFormular(); + var context = Fixture.CrerateContextForm(); var control = new ControlFormItemInputRadio(); var html = control.Render(context).Trim(); @@ -53,7 +53,7 @@ public void Empty() public void True() { // preconditions - var context = Fixture.CrerateContextFormular(); + var context = Fixture.CrerateContextForm(); var control = new ControlFormItemInputRadio() { Checked = true }; var html = control.Render(context).Trim(); @@ -69,7 +69,7 @@ public void True() public void False() { // preconditions - var context = Fixture.CrerateContextFormular(); + var context = Fixture.CrerateContextForm(); var control = new ControlFormItemInputRadio() { Checked = false }; var html = control.Render(context).Trim(); @@ -85,7 +85,7 @@ public void False() public void Description() { // preconditions - var context = Fixture.CrerateContextFormular(); + var context = Fixture.CrerateContextForm(); var control = new ControlFormItemInputRadio() { Description = "abcdefg" }; var html = control.Render(context).Trim(); diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs index 6fddb8c5..ab3a54d6 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs @@ -1,5 +1,4 @@ -ο»Ώusing System.Globalization; -using WebExpress.WebUI.Test.Fixture; +ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; using Xunit.Abstractions; @@ -21,7 +20,7 @@ public class UnitTestControlList : IClassFixture protected UnitTestControlFixture Fixture { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. @@ -67,7 +66,7 @@ public void EmptyListGroup() public void SimpleListAtRender() { // preconditions - var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var context = new WebCore.WebPage.RenderContext() { }; var item = new ControlListItem(new ControlText() { Text = "abc" }); var control = new ControlList(); @@ -83,7 +82,7 @@ public void SimpleListAtRender() public void SimpleListAtInstancing() { // preconditions - var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var context = new WebCore.WebPage.RenderContext() { }; var item = new ControlListItem(new ControlText() { Text = "abc" }); var control = new ControlList(item); @@ -99,7 +98,7 @@ public void SimpleListAtInstancing() public void SimpleListAtAdd() { // preconditions - var context = new WebCore.WebPage.RenderContext() { Culture = CultureInfo.CurrentCulture }; + var context = new WebCore.WebPage.RenderContext() { }; var item = new ControlListItem(new ControlText() { Text = "abc" }); var control = new ControlList(); diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs similarity index 85% rename from src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs rename to src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs index fe942893..cae74398 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlModalFormular.cs +++ b/src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs @@ -5,9 +5,9 @@ namespace WebExpress.WebUI.Test.Control { /// - /// Tests the modal formular control. + /// Tests the modal form control. /// - public class UnitTestControlModalFormular : IClassFixture + public class UnitTestControlModalForm : IClassFixture { /// /// Returns the log. @@ -20,11 +20,11 @@ public class UnitTestControlModalFormular : IClassFixture - /// Constructor + /// Initializes a new instance of the class. /// /// The log. /// The test context. - public UnitTestControlModalFormular(UnitTestControlFixture fixture, ITestOutputHelper output) + public UnitTestControlModalForm(UnitTestControlFixture fixture, ITestOutputHelper output) { Fixture = fixture; Output = output; @@ -38,7 +38,7 @@ public void EmptyForm() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlModalFormular(); + var control = new ControlModalForm(); var html = control.Render(context); var str = html.ToString(); @@ -55,7 +55,7 @@ public void EmptyFormWithId() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlModalFormular("form"); + var control = new ControlModalForm("form"); var html = control.Render(context); @@ -71,7 +71,7 @@ public void EmptyFormWithHeaderAtInstancing() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlModalFormular("form", "header"); + var control = new ControlModalForm("form", "header"); var html = control.Render(context); @@ -87,7 +87,7 @@ public void EmptyFormWithHeaderAtProperty() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlModalFormular("form") { Header = "header" }; + var control = new ControlModalForm("form") { Header = "header" }; var html = control.Render(context); @@ -104,7 +104,7 @@ public void SimpleFormAtRender() { // preconditions var context = Fixture.CrerateContext(); - var control = new ControlModalFormular(); + var control = new ControlModalForm(); var item = new ControlFormItemInputTextBox() { }; // test execution @@ -124,7 +124,7 @@ public void SimpleFormAtInstancing() // preconditions var context = Fixture.CrerateContext(); var item = new ControlFormItemInputTextBox() { }; - var control = new ControlModalFormular("form", item); + var control = new ControlModalForm("form", item); // test execution var html = control.Render(context); @@ -142,7 +142,7 @@ public void SimpleFormAtAdd() // preconditions var context = Fixture.CrerateContext(); var item = new ControlFormItemInputTextBox() { }; - var control = new ControlModalFormular("form"); + var control = new ControlModalForm("form"); control.Add(item); diff --git a/src/WebExpress.WebUI.Test/Data/ComplexForm.txt b/src/WebExpress.WebUI.Test/Data/ComplexForm.txt new file mode 100644 index 00000000..b56a47cf --- /dev/null +++ b/src/WebExpress.WebUI.Test/Data/ComplexForm.txt @@ -0,0 +1,30 @@ +ο»Ώ + + +
          + +

          FragmentHeaderPrimary

          +
          +
          +
          +
          + + + Help1 +
          +
          + + + Help2 +
          +
          +
          +
          + +
          +
          + \ No newline at end of file diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index 171c2130..d1470572 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -3,18 +3,62 @@ using System.Net; using System.Reflection; using WebExpress.WebCore; +using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebLog; using WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPage; +using WebExpress.WebCore.WebPlugin; +using WebExpress.WebCore.WebResource; using WebExpress.WebUI.WebControl; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.Fixture { - public class UnitTestControlFixture + public class UnitTestControlFixture : IDisposable { /// - /// Create a fake render context; + /// Returns a guard to protect against concurrent access. + /// + private static object guard = new object(); + + /// + /// Initializes a new instance of the class and boot the component manager. + /// + public UnitTestControlFixture() + { + lock (guard) + { + if (ComponentManager.PluginManager != null) + { + return; + } + + var initializationComponentManager = typeof(ComponentManager).GetMethod("Initialization", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, [typeof(IHttpServerContext)]); + var registerPluginManager = typeof(PluginManager).GetMethod("Register", BindingFlags.NonPublic | BindingFlags.Instance, [typeof(Assembly), typeof(PluginLoadContext)]); + var serverContext = new HttpServerContext + ( + "localhost", + [], + "", + "", + "", + "", + null, + null, + new Log() { LogMode = LogMode.Off }, + null + ); + + initializationComponentManager.Invoke(null, [serverContext]); + + registerPluginManager.Invoke(ComponentManager.PluginManager, [typeof(Plugin).Assembly, null]); + registerPluginManager.Invoke(ComponentManager.PluginManager, [GetType().Assembly, null]); + } + } + + /// + /// Create a fake render context. /// /// A fake context for testing. public RenderContext CrerateContext() @@ -77,16 +121,60 @@ public RenderContext CrerateContext() var page = new TestPage(); var visualTree = new VisualTreeControl(); - return new WebCore.WebPage.RenderContext(page, request, visualTree); + page.Initialization(CrerateResourceContext()); + + return new RenderContext(page, request, visualTree); + } + + /// + /// Create a fake render form context. + /// + /// A fake context for testing. + public RenderContextForm CrerateContextForm() + { + return new RenderContextForm(CrerateContext(), new ControlForm()); } /// - /// Create a fake render formular context; + /// Create a fake resource context. /// /// A fake context for testing. - public RenderContextFormular CrerateContextFormular() + public ResourceContext CrerateResourceContext() + { + var ctorResourceContext = typeof(ResourceContext).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IModuleContext)], null); + + var moduleContext = ComponentManager.ModuleManager.Modules + .Where(x => x.ModuleId == typeof(TestModule).FullName.ToLower()) + .FirstOrDefault(); + + var resourceContext = (ResourceContext)ctorResourceContext.Invoke([moduleContext]); + + return resourceContext; + } + + /// + /// Gets the content of an embedded resource as a string. + /// + /// The name of the resource file. + /// The content of the embedded resource as a string. + public string GetEmbeddedResource(string fileName) + { + var assembly = GetType().Assembly; + var resourceName = assembly.GetManifestResourceNames() + .FirstOrDefault(name => name.EndsWith(fileName, StringComparison.OrdinalIgnoreCase)); + + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + using (StreamReader reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + + /// + /// Release of unmanaged resources reserved during use. + /// + public void Dispose() { - return new RenderContextFormular(CrerateContext(), new ControlForm()); } } } diff --git a/src/WebExpress.WebUI.Test/TestApplication.cs b/src/WebExpress.WebUI.Test/TestApplication.cs new file mode 100644 index 00000000..af57dd8b --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestApplication.cs @@ -0,0 +1,37 @@ +ο»Ώusing WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebAttribute; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy application for testing purposes. + /// + [Name("webexpress.webui.unittest")] + [Description("plugin.description")] + [Icon("/assets/img/Logo.png")] + [Dependency("webexpress.webui")] + public sealed class TestApplication : IApplication + { + /// + /// Initialization of the application. + /// + /// The application context. + public void Initialization(IApplicationContext applicationContext) + { + } + + /// + /// Called when the plugin starts working. The call is concurrent. + /// + public void Run() + { + } + + /// + /// Release of unmanaged resources reserved during use. + /// + public void Dispose() + { + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestModule.cs b/src/WebExpress.WebUI.Test/TestModule.cs new file mode 100644 index 00000000..92792fb3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestModule.cs @@ -0,0 +1,40 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebModule; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy module for testing purposes. + /// + [Application()] + [Name("module.name")] + [Description("module.description")] + [Icon("/assets/img/Logo.png")] + [AssetPath("/")] + [ContextPath("/")] + public sealed class TestModule : IModule + { + /// + /// Initialization of the module. + /// + /// The module context. + public void Initialization(IModuleContext moduleContext) + { + throw new NotImplementedException(); + } + + /// + /// Called when the plugin starts working. The call is concurrent. + /// + public void Run() + { + } + + /// + /// Release of unmanaged resources reserved during use. + /// + public void Dispose() + { + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestPage.cs b/src/WebExpress.WebUI.Test/TestPage.cs index a625c8ba..21fb5ef2 100644 --- a/src/WebExpress.WebUI.Test/TestPage.cs +++ b/src/WebExpress.WebUI.Test/TestPage.cs @@ -1,7 +1,6 @@ ο»Ώusing System.Globalization; -using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebAttribute; using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPage; using WebExpress.WebCore.WebResource; @@ -10,6 +9,10 @@ namespace WebExpress.WebUI.Test /// /// A dummy class for testing purposes. /// + [Title("webindex:homepage.label")] + [Segment(null, "webindex:homepage.label")] + [ContextPath(null)] + [Module] public sealed class TestPage : IPage { /// @@ -17,25 +20,10 @@ public sealed class TestPage : IPage /// public string Title { get; set; } - /// - /// Returns or sets the ID of the page. - /// - public string Id { get; set; } - - /// - /// Returns or sets the application context. - /// - public IApplicationContext ApplicationContext { get; set; } - - /// - /// Returns or sets the module context. - /// - public IModuleContext ModuleContext { get; set; } - /// /// Returns or sets the resource context. /// - public IResourceContext ResourceContext { get; set; } + public IResourceContext ResourceContext { get; private set; } /// /// Returns or sets the culture information. @@ -43,12 +31,12 @@ public sealed class TestPage : IPage public CultureInfo Culture { get => CultureInfo.CurrentCulture; set => throw new NotImplementedException(); } /// - /// Initializes the resource context. + /// Instillation of the resource. Here, for example, managed resources can be loaded. /// - /// The resource context. + /// The context of the resource. public void Initialization(IResourceContext resourceContext) { - + ResourceContext = resourceContext; } /// diff --git a/src/WebExpress.WebUI.Test/TestPlugin.cs b/src/WebExpress.WebUI.Test/TestPlugin.cs new file mode 100644 index 00000000..e73e439c --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestPlugin.cs @@ -0,0 +1,37 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebPlugin; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy plugin for testing purposes. + /// + [Name("webexpress.webui.unittest")] + [Description("plugin.description")] + [Icon("/assets/img/Logo.png")] + [Dependency("webexpress.webui")] + public sealed class TestPlugin : IPlugin + { + /// + /// Initialization of the plugin. + /// + /// The plugin context. + public void Initialization(IPluginContext pluginContext) + { + } + + /// + /// Called when the plugin starts working. The call is concurrent. + /// + public void Run() + { + } + + /// + /// Release of unmanaged resources reserved during use. + /// + public void Dispose() + { + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj index b74770e4..a9407b28 100644 --- a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj +++ b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj @@ -10,6 +10,10 @@ Debug;Release;Test + + + + @@ -24,4 +28,8 @@ + + + + diff --git a/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs b/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs new file mode 100644 index 00000000..69277ad3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs @@ -0,0 +1,27 @@ +ο»Ώusing WebExpress.WebApp.WebSection; +using WebExpress.WebCore.WebAttribute; +using WebExpress.WebUI.WebAttribute; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; +using static System.Collections.Specialized.BitVector32; + +namespace WebExpress.WebUI.Test.WebFragment +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section(SectionControl.HeaderPrimary)] + [Module] + [Scope] + public sealed class FragmentHeaderPrimary : FragmentControlText + { + /// + /// Initializes a new instance of the class. + /// + public FragmentHeaderPrimary() + { + Text = "FragmentHeaderPrimary"; + Format = TypeFormatText.Paragraph; + } + } +} diff --git a/src/WebExpress.WebUI/Assets/css/webexpress.webui.modalformular.css b/src/WebExpress.WebUI/Assets/css/webexpress.webui.modalform.css similarity index 71% rename from src/WebExpress.WebUI/Assets/css/webexpress.webui.modalformular.css rename to src/WebExpress.WebUI/Assets/css/webexpress.webui.modalform.css index 8072b5c6..e703cfe7 100644 --- a/src/WebExpress.WebUI/Assets/css/webexpress.webui.modalformular.css +++ b/src/WebExpress.WebUI/Assets/css/webexpress.webui.modalform.css @@ -1,7 +1,7 @@ -.modalformular { +.modalform { } - .modalformular > .modal-dialog > form { + .modalform > .modal-dialog > form { background-color: transparent !important; border: none !important; margin: 0 !important; diff --git a/src/WebExpress.WebUI/Assets/js/webexpress.webui.modalformular.js b/src/WebExpress.WebUI/Assets/js/webexpress.webui.modalform.js similarity index 94% rename from src/WebExpress.WebUI/Assets/js/webexpress.webui.modalformular.js rename to src/WebExpress.WebUI/Assets/js/webexpress.webui.modalform.js index f7dd2d9d..ce85b37d 100644 --- a/src/WebExpress.WebUI/Assets/js/webexpress.webui.modalformular.js +++ b/src/WebExpress.WebUI/Assets/js/webexpress.webui.modalform.js @@ -1,11 +1,11 @@ /** - * A modular formular. + * A modular form. * The following events are triggered: * - webexpress.webui.close */ -webexpress.webui.modalFormularCtrl = class extends webexpress.webui.events { +webexpress.webui.modalFormCtrl = class extends webexpress.webui.events { _uri = null; - _container = $(""); + _container = $(""); /** * Constructor diff --git a/src/WebExpress.WebUI/Module.cs b/src/WebExpress.WebUI/Module.cs index f1d57ce3..7355f7f6 100644 --- a/src/WebExpress.WebUI/Module.cs +++ b/src/WebExpress.WebUI/Module.cs @@ -12,7 +12,7 @@ namespace WebExpress.WebUI public sealed class Module : WebCore.WebModule.Module { /// - /// Constructor + /// Initializes a new instance of the class. /// public Module() { diff --git a/src/WebExpress.WebUI/Plugin.cs b/src/WebExpress.WebUI/Plugin.cs index 42713697..d6cec901 100644 --- a/src/WebExpress.WebUI/Plugin.cs +++ b/src/WebExpress.WebUI/Plugin.cs @@ -11,7 +11,7 @@ namespace WebExpress.WebUI public sealed class Plugin : WebCore.WebPlugin.Plugin { /// - /// Constructor + /// Initializes a new instance of the class. /// public Plugin() { diff --git a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs index aa0ae11e..31f241ac 100644 --- a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebAttribute public class OptionAttribute : System.Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The option to activate. public OptionAttribute(string option) diff --git a/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs b/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs index 7fbbeeef..c5e0738f 100644 --- a/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs @@ -6,7 +6,7 @@ public class OrderAttribute : System.Attribute, IFragmentAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The order within the section. public OrderAttribute(int order) diff --git a/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs index d41c042a..6a41cd8f 100644 --- a/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs @@ -6,7 +6,7 @@ public class SectionAttribute : System.Attribute, IFragmentAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The section where the component is embedded. public SectionAttribute(string section) diff --git a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs index 7b7a747a..353af4e3 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebAttribute public class SettingContextAttribute : Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The context in which the settings page is associated. public SettingContextAttribute(string context) diff --git a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs index 02e1b11d..531cc453 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebAttribute public class SettingGroupAttribute : System.Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The group name. public SettingGroupAttribute(string name) diff --git a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs index d374cfb0..6a9ecc30 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.WebAttribute public class SettingHideAttribute : System.Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// public SettingHideAttribute() { diff --git a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs index 1be9ba84..35f7bf95 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebAttribute public class SettingIconAttribute : System.Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The icon. public SettingIconAttribute(TypeIcon icon) @@ -15,7 +15,7 @@ public SettingIconAttribute(TypeIcon icon) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The icon. public SettingIconAttribute(string icon) diff --git a/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs index 58e88a05..f676c888 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebAttribute public class SettingSectionAttribute : System.Attribute, IResourceAttribute { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The section where the settings page is listed. public SettingSectionAttribute(SettingSection section) diff --git a/src/WebExpress.WebUI/WebControl/Control.cs b/src/WebExpress.WebUI/WebControl/Control.cs index 4d1a30e2..e3093345 100644 --- a/src/WebExpress.WebUI/WebControl/Control.cs +++ b/src/WebExpress.WebUI/WebControl/Control.cs @@ -142,7 +142,7 @@ public virtual TypeHeight Height public abstract IHtmlNode Render(RenderContext context); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. public Control(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlArlert.cs b/src/WebExpress.WebUI/WebControl/ControlArlert.cs index 164959a6..161bf7d2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlArlert.cs +++ b/src/WebExpress.WebUI/WebControl/ControlArlert.cs @@ -46,7 +46,7 @@ public TypeFade Fade public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlAlert(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs index f26ffe48..3fe0b0c1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs @@ -37,7 +37,7 @@ public class ControlAttribute : Control public Uri Uri { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlAttribute(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs index f21b6aca..51725771 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs @@ -32,7 +32,7 @@ public TypeSizeButton Size public ControlModal Modal { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlAvatar(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlBadge.cs b/src/WebExpress.WebUI/WebControl/ControlBadge.cs index 2db07e4c..f4c0be55 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBadge.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBadge.cs @@ -56,7 +56,7 @@ public PropertySizeText Size } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlBadge(string id = null) @@ -66,7 +66,7 @@ public ControlBadge(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The value. @@ -79,7 +79,7 @@ public ControlBadge(string id, string value) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The value. diff --git a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs index 80e8276a..828f8150 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs @@ -36,7 +36,7 @@ public TypeSizeButton Size public ushort TakeLast { get; set; } = ushort.MaxValue; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlBreadcrumb(string id = null) @@ -46,7 +46,7 @@ public ControlBreadcrumb(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// Der Verzeichnispfad diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index 8b7a3bc4..3cb4a024 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -75,7 +75,7 @@ public TypeActive Active } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlButton(string id = null) @@ -145,9 +145,9 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormularCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } else if (Modal.Type == TypeModal.Brwoser) { diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index 79b7317e..ca4e155c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -18,7 +18,7 @@ public class ControlButtonLink : ControlButton public string Title { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlButtonLink(string id = null) @@ -43,7 +43,7 @@ private void Init() /// The control as html. public override IHtmlNode Render(RenderContext context) { - var text = InternationalizationManager.I18N(context.Culture, Text); + var text = context.I18N(Text); var html = new HtmlElementTextSemanticsA() { @@ -86,9 +86,9 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormularCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) diff --git a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs index eb1835f5..9db1cd0e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs @@ -12,7 +12,7 @@ public class ControlCanvas : Control public List Content { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlCanvas(string id = null) @@ -22,7 +22,7 @@ public ControlCanvas(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlCanvas(params Control[] content) @@ -32,7 +32,7 @@ public ControlCanvas(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. @@ -43,7 +43,7 @@ public ControlCanvas(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. @@ -54,7 +54,7 @@ public ControlCanvas(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs index 72cd3adc..7329ec96 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs @@ -29,7 +29,7 @@ public class ControlCardCounter : ControlPanelCard public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlCardCounter(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs index b5134b40..13306a39 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs @@ -15,7 +15,7 @@ public class ControlCarousel : Control public List Items { get; private set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlCarousel(string id = null) @@ -24,7 +24,7 @@ public ControlCarousel(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The contents of the slideshow. public ControlCarousel(params ControlCarouselItem[] items) diff --git a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs index 31545ef8..d04fad99 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs @@ -21,7 +21,7 @@ public class ControlCarouselItem public IControl Control { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public ControlCarouselItem() { diff --git a/src/WebExpress.WebUI/WebControl/ControlChart.cs b/src/WebExpress.WebUI/WebControl/ControlChart.cs index 2ecc165a..60d1db3d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChart.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChart.cs @@ -62,7 +62,7 @@ public class ControlChart : Control public ICollection Data { get; set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlChart(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs index 04cca96c..919ec0b4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs @@ -35,7 +35,7 @@ public class ControlChartDataset public TypePointChart Point { get; set; } = TypePointChart.Circle; /// - /// Constructor + /// Initializes a new instance of the class. /// public ControlChartDataset() { diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs index a5b84492..c4980585 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs @@ -107,7 +107,7 @@ public TypeAlignmentDropdownMenu AlignmentMenu public new int Width { get; set; } = -1; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlDropdown(string id = null) @@ -117,7 +117,7 @@ public ControlDropdown(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -130,7 +130,7 @@ public ControlDropdown(string id, params IControlDropdownItem[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlDropdown(params IControlDropdownItem[] content) @@ -142,7 +142,7 @@ public ControlDropdown(params IControlDropdownItem[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. @@ -155,7 +155,7 @@ public ControlDropdown(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlDropdown(IEnumerable content) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs index d1c17b64..2ae1da7c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebControl public class ControlDropdownItemDivider : Control, IControlDropdownItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlDropdownItemDivider(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs index 5f74ce53..17bde0a1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs @@ -11,7 +11,7 @@ public class ControlDropdownItemHeader : Control, IControlDropdownItem public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlDropdownItemHeader(string id = null) @@ -21,7 +21,7 @@ public ControlDropdownItemHeader(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index 0adb46e7..82b9c6ec 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.WebControl public class ControlDropdownItemLink : ControlLink, IControlDropdownItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlDropdownItemLink(string id = null) @@ -33,7 +33,7 @@ public override IHtmlNode Render(RenderContext context) Role = Role, Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), Target = Target, - Title = InternationalizationManager.I18N(context.Culture, Title), + Title = context.I18N(Title), OnClick = OnClick?.ToString() }; @@ -61,9 +61,9 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormularCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index deb20302..ba665c1f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -1,20 +1,56 @@ ο»Ώusing System; using System.Collections.Generic; using System.Linq; +using WebExpress.WebApp.WebSection; using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebMessage; using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +using WebExpress.WebCore.WebScope; +using WebExpress.WebUI.WebFragment; namespace WebExpress.WebUI.WebControl { - public class ControlForm : Control, IControlForm + /// + /// Represents a form with various input fields and controls. + /// + public class ControlForm : Control, IControlForm, IScope { /// - /// Returns or sets the layout. + /// Returns the form items. + /// + private List _items = []; + + /// + /// Returns the preferences form control buttons. + /// + private List _preferencesButtons = []; + + /// + /// Returns the primary form control buttons. /// - public virtual TypeLayoutForm Layout { get; set; } = TypeLayoutForm.Vertical; + private List _primaryButtons = []; + + /// + /// Returns the secondary form control buttons. + /// + private List _secondaryButtons = []; + + /// + /// Returns the preferences controls. + /// + private List _preferencesControls = []; + + /// + /// Returns the primary controls. + /// + private List _primaryControls = []; + + /// + /// Returns the secondary controls. + /// + private List _secondaryControls = []; /// /// Event to validate the input values. @@ -29,22 +65,22 @@ public class ControlForm : Control, IControlForm /// /// Event is raised when the form has been initialized. /// - public event EventHandler InitializeFormular; + public event EventHandler InitializeForm; /// /// Event is raised when the form's data needs to be determined. /// - public event EventHandler FillFormular; + public event EventHandler FillForm; /// /// Event is raised when the form is about to be processed. /// - public event EventHandler ProcessFormular; + public event EventHandler ProcessForm; /// /// Event is raised when the form is to be processed and the next data is to be loaded. /// - public event EventHandler ProcessAndNextFormular; + public event EventHandler ProcessAndNextForm; /// /// Returns or sets the name of the form. @@ -61,12 +97,22 @@ public class ControlForm : Control, IControlForm /// public string RedirectUri { get; set; } + /// + /// Returns or sets the form layout. + /// + public virtual TypeLayoutForm FormLayout { get; set; } = TypeLayoutForm.Default; + + /// + /// Returns or sets the item layout. + /// + public virtual TypeLayoutFormItem ItemLayout { get; set; } = TypeLayoutFormItem.Vertical; + /// /// Returns or sets the hidden field that contains the id. /// - public ControlFormItemInputHidden FormularId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) + public ControlFormItemInputHidden FormId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) { - Name = "formular-id" + Name = "form-id" }; /// @@ -74,60 +120,92 @@ public class ControlForm : Control, IControlForm /// public ControlFormItemInputHidden SubmitType { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) { - Name = "formular-submit-type", + Name = "form-submit-type", Value = "update" }; /// - /// Returns or sets the submit button. + /// Returns or sets the request method. /// - public ControlFormItemButton SubmitButton { get; } = new ControlFormItemButton() - { - Icon = new PropertyIcon(TypeIcon.Save), - Color = new PropertyColorButton(TypeColorButton.Success), - Type = TypeButton.Submit, - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None), - }; + public RequestMethod Method { get; set; } = RequestMethod.POST; /// - /// Returns or sets the request method. + /// Returns or sets the header preferences section. /// - public RequestMethod Method { get; set; } = RequestMethod.POST; + protected List HeaderPreferences { get; } = []; /// - /// Returns the form items. + /// Returns or sets the header primary section. + /// + protected List HeaderPrimary { get; } = []; + + /// + /// Returns or sets the header secondary section. + /// + protected List HeaderSecondary { get; } = []; + + /// + /// Returns or sets the button panel preferences section. + /// + protected List ButtonPanelPreferences { get; } = []; + + /// + /// Returns or sets the button panel primary section. + /// + protected List ButtonPanelPrimary { get; } = []; + + /// + /// Returns or sets the button panel secondary section. + /// + protected List ButtonPanelSecondary { get; } = []; + + /// + /// Returns or sets the footer preferences section. + /// + protected List FooterPreferences { get; } = []; + + /// + /// Returns or sets the footer primary section. + /// + protected List FooterPrimary { get; } = []; + + /// + /// Returns or sets the footer secondary section. /// - protected List _Items { get; } = new List(); + protected List FooterSecondary { get; } = []; /// /// Returns the form items. /// - public IEnumerable Items => _Items; + public IEnumerable Items => _items; /// - /// Constructor + /// Returns the form buttons. + /// + public IEnumerable Buttons => _preferencesButtons.Union(_primaryButtons).Union(_secondaryButtons); + + /// + /// Initializes a new instance of the class. /// /// The id of the control. public ControlForm(string id = null) : base(id) { - SubmitButton.Name = SubmitButton.Id; - SubmitButton.OnClick = new PropertyOnClick($"$('#{SubmitType.Id}').val('submit');"); } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The controls that are associated with the form. public ControlForm(string id, params ControlFormItem[] items) : this(id) { - _Items.AddRange(items); + _items.AddRange(items); } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The controls that are associated with the form. public ControlForm(params ControlFormItem[] items) @@ -139,31 +217,34 @@ public ControlForm(params ControlFormItem[] items) /// Initializes the form. /// /// The context in which the control is rendered. - public virtual void Initialize(RenderContextFormular context) + public virtual void Initialize(RenderContextForm context) { - // Id ΓΌberprΓΌfen + var fm = ComponentManager.GetComponent(); + + // check id if (string.IsNullOrWhiteSpace(Id)) { - context.Host.Log.Warning(I18N("webexpress.webui:form.empty.id")); + context.ApplicationContext?.PluginContext.Host.Log.Warning(InternationalizationManager.I18N("webexpress.webui:form.empty.id")); } - FormularId.Value = Id; + FormId.Value = Id; - if (string.IsNullOrWhiteSpace(SubmitButton.Text)) - { - SubmitButton.Text = context.I18N("webexpress.webui", "form.submit.label"); - } - else - { - SubmitButton.Text = context.I18N(SubmitButton.Text); - } + // header + HeaderPreferences.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPreferences, context.Page, [GetType().FullName])); + HeaderPrimary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPrimary, context.Page, [GetType().FullName])); + HeaderSecondary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderSecondary, context.Page, [GetType().FullName])); + + // footer + FooterPreferences.AddRange(fm.GetCacheableFragments(SectionControl.FooterPreferences, context.Page, [GetType().FullName])); + FooterPrimary.AddRange(fm.GetCacheableFragments(SectionControl.FooterPrimary, context.Page, [GetType().FullName])); + FooterSecondary.AddRange(fm.GetCacheableFragments(SectionControl.FooterSecondary, context.Page, [GetType().FullName])); } /// /// Filling the form. /// /// The context in which the control is rendered. - public virtual void Fill(RenderContextFormular context) + public virtual void Fill(RenderContextForm context) { OnFill(context); } @@ -173,12 +254,12 @@ public virtual void Fill(RenderContextFormular context) /// /// The context in which the inputs are validated. /// True if all form items are valid, false otherwise. - public virtual bool Validate(RenderContextFormular context) + public virtual bool Validate(RenderContextForm context) { var valid = true; var validationResults = context.ValidationResults as List; - foreach (var v in Items.Where(x => x is IFormularValidation).Select(x => x as IFormularValidation)) + foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) { v.Validate(context); @@ -209,7 +290,7 @@ public virtual bool Validate(RenderContextFormular context) } /// - /// Instructs to reload the initial formular data. + /// Instructs to reload the initial form data. /// public void Reset() { @@ -220,16 +301,16 @@ public void Reset() /// Pre-processing of the form. /// /// The context in which the control is rendered. - public virtual void PreProcess(RenderContextFormular context) + public virtual void PreProcess(RenderContextForm context) { } /// - /// Processing of the resource. des Formulars + /// Processing of the form. /// /// The context in which the control is rendered. - public virtual void Process(RenderContextFormular context) + public virtual void Process(RenderContextForm context) { OnProcess(context); @@ -253,18 +334,18 @@ public override IHtmlNode Render(RenderContext context) /// Convert to html. ///
          /// The context in which the control is rendered. - /// The formular items. + /// The form items. /// The control as html. public virtual IHtmlNode Render(RenderContext context, IEnumerable items) { - var renderContext = new RenderContextFormular(context, this); + var renderContext = new RenderContextForm(context, this); var fill = false; var process = false; // check if and how the form was submitted - if (context.Request.GetParameter("formular-id")?.Value == Id && context.Request.HasParameter("formular-submit-type")) + if (context.Request.GetParameter("form-id")?.Value == Id && context.Request.HasParameter("form-submit-type")) { - var value = context.Request.GetParameter("formular-submit-type")?.Value; + var value = context.Request.GetParameter("form-submit-type")?.Value; switch (value) { case "submit": @@ -293,8 +374,11 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerable x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + header.Elements.AddRange(HeaderSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + foreach (var v in renderContext.ValidationResults) { var bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Default); @@ -354,7 +440,7 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerable new ControlFormItemGroupHorizontal(), - TypeLayoutForm.Mix => new ControlFormItemGroupMix(), + TypeLayoutFormItem.Horizontal => new ControlFormItemGroupHorizontal(), + TypeLayoutFormItem.Mix => new ControlFormItemGroupMix(), _ => new ControlFormItemGroupVertical(), }; @@ -383,11 +469,18 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerable x.Render(renderContext))); + var footer = new HtmlElementSectionFooter(); + footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + + footer.Elements.AddRange(FooterPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + footer.Elements.AddRange(FooterSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - footer.Elements.Add(button); form.Elements.Add(header); form.Elements.Add(main); + form.Elements.Add(buttonPannel); form.Elements.Add(footer); form.Elements.AddRange(renderContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); @@ -403,7 +496,61 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerableThe form item. public void Add(params ControlFormItem[] item) { - _Items.AddRange(item); + _items.AddRange(item); + } + + /// + /// Adds a preferences control. + /// + /// The controls. + public void AddPreferencesControl(params ControlFormItem[] controls) + { + _preferencesControls.AddRange(controls); + } + + /// + /// Adds a preferences form control button. + /// + /// The form buttons. + public void AddPreferencesButton(params ControlFormItemButton[] buttons) + { + _preferencesButtons.AddRange(buttons); + } + + /// + /// Adds a primary control. + /// + /// The controls. + public void AddPrimaryControl(params ControlFormItem[] controls) + { + _primaryControls.AddRange(controls); + } + + /// + /// Adds a primary form control button. + /// + /// The form buttons. + public void AddPrimaryButton(params ControlFormItemButton[] buttons) + { + _primaryButtons.AddRange(buttons); + } + + /// + /// Adds a secondary control. + /// + /// The controls. + public void AddSecondaryControl(params ControlFormItem[] controls) + { + _secondaryControls.AddRange(controls); + } + + /// + /// Adds a secondary form control button. + /// + /// The form buttons. + public void AddSecondaryButton(params ControlFormItemButton[] buttons) + { + _secondaryButtons.AddRange(buttons); } /// @@ -412,43 +559,54 @@ public void Add(params ControlFormItem[] item) /// The form item. public void Remove(ControlFormItem formItem) { - _Items.Remove(formItem); + _items.Remove(formItem); + } + + /// + /// Removes a form control button from the form. + /// + /// The form button. + public void RemoveButton(ControlFormItemButton button) + { + _preferencesButtons.Remove(button); + _primaryButtons.Remove(button); + _secondaryButtons.Remove(button); } /// /// Raises the process event. /// /// The context in which the control is rendered. - protected virtual void OnProcess(RenderContextFormular context) + protected virtual void OnProcess(RenderContextForm context) { - ProcessFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + ProcessForm?.Invoke(this, new FormEventArgs() { Context = context }); } /// /// Raises the process event. /// /// The context in which the control is rendered. - protected virtual void OnProcessAndNextFormular(RenderContextFormular context) + protected virtual void OnProcessAndNextForm(RenderContextForm context) { - ProcessAndNextFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + ProcessAndNextForm?.Invoke(this, new FormEventArgs() { Context = context }); } /// /// Raises the Initializations event. /// /// The context in which the control is rendered. - protected virtual void OnInitialize(RenderContextFormular context) + protected virtual void OnInitialize(RenderContextForm context) { - InitializeFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + InitializeForm?.Invoke(this, new FormEventArgs() { Context = context }); } /// /// Raises the data delivery event. /// /// The context in which the control is rendered. - protected virtual void OnFill(RenderContextFormular context) + protected virtual void OnFill(RenderContextForm context) { - FillFormular?.Invoke(this, new FormularEventArgs() { Context = context }); + FillForm?.Invoke(this, new FormEventArgs() { Context = context }); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs b/src/WebExpress.WebUI/WebControl/ControlFormInline.cs deleted file mode 100644 index 3fd08511..00000000 --- a/src/WebExpress.WebUI/WebControl/ControlFormInline.cs +++ /dev/null @@ -1,371 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormInline : Control, IControlForm - { - /// - /// Event to validate the input values. - /// - public event EventHandler Validation; - - /// - /// Event is raised when the form has been initialized. - /// - public event EventHandler InitializeFormular; - - /// - /// Event is raised when the form's data needs to be determined. - /// - public event EventHandler FillFormular; - - /// - /// Event is raised when the form is about to be processed. - /// - public event EventHandler ProcessFormular; - - /// - /// Event is raised when the form is to be processed and the next data is to be loaded. - /// - public event EventHandler ProcessAndNextFormular; - - /// - /// Returns or sets the name of the form. - /// - public string Name { get; set; } - - /// - /// Returns or sets the target uri. - /// - public string Uri { get; set; } - - /// - /// Returns or sets the redirect uri. - /// - public string RedirectUri { get; set; } - - /// - /// Returns or sets the abort uri. - /// - public string BackUri { get; set; } - - /// - /// Returns or sets the submit button. - /// - public ControlFormItemButton SubmitButton { get; private set; } - - /// - /// Returns or sets the scope of the form data. - /// - public ParameterScope Scope { get; set; } - - /// - /// Returns or sets the request method. - /// - public RequestMethod Method { get; set; } = RequestMethod.POST; - - /// - /// Returns the form items. - /// - protected List _Items { get; } = new List(); - - /// - /// Returns the form items. - /// - public IEnumerable Items => _Items; - - /// - /// Returns the validation results. - /// - public ICollection ValidationResults { get; } = new List(); - - /// - /// Constructor - /// - /// The id of the control. - public ControlFormInline(string id = null) - : base(id) - { - Name = Id != null ? Id.StartsWith("formular") ? Id : $"formular_{Id}" : "formular"; - - SubmitButton = new ControlFormItemButton("submit-" + Name?.ToLower()) - { - Name = "submit-" + Name?.ToLower(), - Icon = new PropertyIcon(TypeIcon.Save), - Color = new PropertyColorButton(TypeColorButton.Success), - Type = TypeButton.Submit, - Value = "1", - Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None) - }; - } - - /// - /// Constructor - /// - /// The id. - /// The controls that are associated with the form. - public ControlFormInline(string id, params ControlFormItem[] items) - : this(id) - { - _Items.AddRange(items); - - } - - /// - /// Constructor - /// - /// The controls that are associated with the form. - public ControlFormInline(params ControlFormItem[] items) - : this(null, items) - { - } - - /// - /// Initializes the form. - /// - /// The context in which the control is rendered. - public virtual void Initialize(RenderContextFormular context) - { - if (string.IsNullOrWhiteSpace(SubmitButton.Text)) - { - SubmitButton.Text = context.I18N("webexpress.webui", "form.submit.label"); - } - } - - /// - /// Adds a form element. - /// - /// The form item. - public void Add(params ControlFormItem[] item) - { - _Items.AddRange(item); - } - - /// - /// Removes a form control item from the form. - /// - /// The form item. - public void Remove(ControlFormItem formItem) - { - _Items.Remove(formItem); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcess(RenderContextFormular context) - { - ProcessFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcessAndNextFormular(RenderContextFormular context) - { - ProcessAndNextFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the store event. - /// - /// The context in which the control is rendered. - protected virtual void OnInitialize(RenderContextFormular context) - { - InitializeFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the data delivery event. - /// - /// The context in which the control is rendered. - protected virtual void OnFill(RenderContextFormular context) - { - FillFormular?.Invoke(this, new FormularEventArgs() { Context = context }); - } - - /// - /// Raises the validation event. - /// - /// The event argument. - protected virtual void OnValidation(ValidationEventArgs e) - { - Validation?.Invoke(this, e); - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - /// True if all form items are valid, false otherwise. - public virtual bool Validate(RenderContextFormular context) - { - var valid = true; - var validationResults = ValidationResults as List; - - validationResults.Clear(); - - foreach (var v in Items.Where(x => x is IFormularValidation).Select(x => x as IFormularValidation)) - { - v.Validate(context); - - if (v.ValidationResult == TypesInputValidity.Error) - { - valid = false; - } - - validationResults.AddRange(v.ValidationResults); - } - - var args = new ValidationEventArgs() { Value = null, Context = context }; - OnValidation(args); - - validationResults.AddRange(args.Results); - - if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - valid = false; - } - - return valid; - } - - /// - /// Vorverarbeitung des Formulars - /// - /// The context in which the control is rendered. - public virtual void PreProcess(RenderContextFormular context) - { - - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return Render(context, Items); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The formular items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, IEnumerable items) - { - var renderContext = new RenderContextFormular(context, this); - var formName = Name != null ? Name.StartsWith("formular") ? Name : $"formular_{Name}" : "formular"; - - Initialize(renderContext); - (Items as List).ForEach(x => x.Initialize(renderContext)); - OnInitialize(renderContext); - SubmitButton.Initialize(renderContext); - - // PrΓΌfe ob Formular abgeschickt wurde -> Fomular mit Daten fΓΌllen - if (!context.Request.HasParameter("submit-" + formName)) - { - OnFill(renderContext); - } - - PreProcess(renderContext); - - var button = SubmitButton.Render(renderContext); - - if (context.Request.HasParameter("formular-id")) - { - var value = context.Request.GetParameter("formular-id")?.Value; - - if (!string.IsNullOrWhiteSpace(Id) && value == Id) - { - var valid = Validate(renderContext); - - if (valid) - { - OnProcess(renderContext); - - if (!string.IsNullOrWhiteSpace(RedirectUri?.ToString())) - { - renderContext.Page.Redirecting(RedirectUri); - } - } - } - } - - var html = new HtmlElementFormForm() - { - Id = Id, - Class = Css.Concatenate("form-inline", GetClasses()), - Style = GetStyles(), - Role = Role, - Name = formName.ToLower(), - Action = Uri?.ToString(), - Method = Method.ToString(), - Enctype = TypeEnctype.None - }; - - html.Elements.Add(new ControlFormItemInputHidden() { Name = "formular-id", Value = Id }.Render(renderContext)); - - foreach (var item in items) - { - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormularItem = item; - label.Classes.Add("me-2"); - help.Text = context.I18N(input?.Help); - help.Classes.Add("ms-2"); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) - { - Style = "display: flex;" - }); - } - else - { - fieldset.Elements.Add(label.Render(renderContext)); - } - - fieldset.Elements.Add(item.Render(renderContext)); - - if (input != null) - { - fieldset.Elements.Add(help.Render(renderContext)); - } - - html.Elements.Add(fieldset); - } - else - { - html.Elements.Add(item.Render(context)); - } - } - - html.Elements.Add(button); - - return html; - } - } -} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs index 54cca018..dc343b49 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs @@ -11,7 +11,7 @@ public abstract class ControlFormItem : Control public string Name { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItem(string id = null) @@ -23,14 +23,14 @@ public ControlFormItem(string id = null) /// Initializes the form element. /// /// The context in which the control is rendered. - public abstract void Initialize(RenderContextFormular context); + public abstract void Initialize(RenderContextForm context); /// /// Convert to html. /// /// The context in which the control is rendered. /// The control as html. - public abstract IHtmlNode Render(RenderContextFormular context); + public abstract IHtmlNode Render(RenderContextForm context); /// /// Convert to html. @@ -39,7 +39,7 @@ public ControlFormItem(string id = null) /// The control as html. public override IHtmlNode Render(RenderContext context) { - if (context is RenderContextFormular formContext) + if (context is RenderContextForm formContext) { return Render(formContext); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs index 87795901..e0d44c7d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs @@ -53,7 +53,7 @@ public TypeBlockButton Block /// /// Event is triggered when the button is clicked. /// - public EventHandler Click; + public EventHandler Click; /// /// Returns or sets the text. @@ -76,7 +76,7 @@ public TypeBlockButton Block public PropertyIcon Icon { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemButton(string id = null) @@ -88,7 +88,7 @@ public ControlFormItemButton(string id = null) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { Disabled = false; Size = TypeSizeButton.Default; @@ -99,7 +99,7 @@ public override void Initialize(RenderContextFormular context) if (!string.IsNullOrWhiteSpace(Value) && value == Value) { - OnClickEvent(new FormularEventArgs() { Context = context }); + OnClickEvent(new FormEventArgs() { Context = context }); } } } @@ -109,7 +109,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var html = new HtmlElementFieldButton() { @@ -157,7 +157,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Triggers the click event. /// /// The event argument. - protected virtual void OnClickEvent(FormularEventArgs e) + protected virtual void OnClickEvent(FormEventArgs e) { Click?.Invoke(this, e); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs new file mode 100644 index 00000000..f29aa7e4 --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.Internationalization; + +namespace WebExpress.WebUI.WebControl +{ + public class ControlFormItemButtonSubmit : ControlFormItemButton + { + /// + /// Initializes a new instance of the class. + /// + /// The control id. + public ControlFormItemButtonSubmit(string id) + : base(id) + { + Name = Id; + Text = InternationalizationManager.I18N("webexpress.webui", "form.submit.label"); + Icon = new PropertyIcon(TypeIcon.Save); + Color = new PropertyColorButton(TypeColorButton.Success); + Type = TypeButton.Submit; + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); + OnClick = new PropertyOnClick($"$('#{Id}').val('submit');"); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs index 32460fea..4d68c1b8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebControl /// /// Grouping of controls. /// - public abstract class ControlFormItemGroup : ControlFormItem, IFormularValidation + public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation { /// /// Returns or sets the form items. @@ -50,7 +50,7 @@ public virtual TypesInputValidity ValidationResult } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroup(string id = null) @@ -59,7 +59,7 @@ public ControlFormItemGroup(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form item. @@ -70,7 +70,7 @@ public ControlFormItemGroup(string id, params ControlFormItem[] item) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form item. public ControlFormItemGroup(params ControlFormItem[] item) @@ -83,9 +83,9 @@ public ControlFormItemGroup(params ControlFormItem[] item) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var groupContex = new RenderContextFormularGroup(context, this); + var groupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -97,13 +97,13 @@ public override void Initialize(RenderContextFormular context) /// Checks the input element for correctness of the data. ///
          /// The context in which the inputs are validated. - public virtual void Validate(RenderContextFormular context) + public virtual void Validate(RenderContextForm context) { var validationResults = ValidationResults as List; validationResults.Clear(); - foreach (var v in Items.Where(x => x is IFormularValidation).Select(x => x as IFormularValidation)) + foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) { v.Validate(context); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs index 04da3ffd..d83ed0ce 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs @@ -15,7 +15,7 @@ public class ControlFormItemGroupColumn : ControlFormItemGroup public ICollection Distribution { get; set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupColumn(string id = null) @@ -24,7 +24,7 @@ public ControlFormItemGroupColumn(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -34,7 +34,7 @@ public ControlFormItemGroupColumn(string id, params ControlFormItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupColumn(params ControlFormItem[] items) @@ -46,9 +46,9 @@ public ControlFormItemGroupColumn(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -61,9 +61,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -88,7 +88,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; label.Classes.Add("me-2"); help.Text = context.I18N(input?.Help); help.Classes.Add("ms-2"); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs index 0538f0b3..b0171668 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupColumnHorizontal : ControlFormItemGroupColumn { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupColumnHorizontal(string id = null) @@ -19,7 +19,7 @@ public ControlFormItemGroupColumnHorizontal(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -29,7 +29,7 @@ public ControlFormItemGroupColumnHorizontal(string id, params ControlFormItem[] } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) @@ -41,9 +41,9 @@ public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -56,9 +56,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -103,7 +103,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; help.Text = context.I18N(input?.Help); if (icon.Icon != null) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs index 47ca5ba7..e527a3f2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupColumnMix : ControlFormItemGroupColumn { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupColumnMix(string id = null) @@ -19,7 +19,7 @@ public ControlFormItemGroupColumnMix(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -29,7 +29,7 @@ public ControlFormItemGroupColumnMix(string id, params ControlFormItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupColumnMix(params ControlFormItem[] items) @@ -41,9 +41,9 @@ public ControlFormItemGroupColumnMix(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -56,9 +56,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -103,7 +103,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; help.Text = context.I18N(input?.Help); if (icon.Icon != null) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs index 416d5e7e..7a4f6a89 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupColumnVertical : ControlFormItemGroupColumn { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupColumnVertical(string id = null) @@ -19,7 +19,7 @@ public ControlFormItemGroupColumnVertical(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -29,7 +29,7 @@ public ControlFormItemGroupColumnVertical(string id, params ControlFormItem[] it } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupColumnVertical(params ControlFormItem[] items) @@ -41,9 +41,9 @@ public ControlFormItemGroupColumnVertical(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -56,9 +56,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -100,7 +100,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; help.Text = context.I18N(input?.Help); if (icon.Icon != null) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs index d7bdbb32..60b9f3d3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs @@ -9,7 +9,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupHorizontal : ControlFormItemGroup { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupHorizontal(string id = null) @@ -18,7 +18,7 @@ public ControlFormItemGroupHorizontal(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -28,7 +28,7 @@ public ControlFormItemGroupHorizontal(string id, params ControlFormItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupHorizontal(params ControlFormItem[] items) @@ -40,9 +40,9 @@ public ControlFormItemGroupHorizontal(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -55,9 +55,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -82,7 +82,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; label.Classes.Add("me-2"); help.Text = context.I18N(input?.Help); help.Classes.Add("ms-2"); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs index 3c6ab1f9..5076ca60 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs @@ -9,7 +9,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupMix : ControlFormItemGroup { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupMix(string id = null) @@ -18,7 +18,7 @@ public ControlFormItemGroupMix(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -28,7 +28,7 @@ public ControlFormItemGroupMix(string id, params ControlFormItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupMix(params ControlFormItem[] items) @@ -40,9 +40,9 @@ public ControlFormItemGroupMix(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -55,9 +55,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -82,7 +82,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; label.Classes.Add("me-2"); help.Text = context.I18N(input?.Help); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs index 58ef415e..2c5dd6e1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs @@ -9,7 +9,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemGroupVertical : ControlFormItemGroup { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemGroupVertical(string id = null) @@ -18,7 +18,7 @@ public ControlFormItemGroupVertical(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. ///The form controls. @@ -28,7 +28,7 @@ public ControlFormItemGroupVertical(string id, params ControlFormItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// ///The form controls. public ControlFormItemGroupVertical(params ControlFormItem[] items) @@ -40,9 +40,9 @@ public ControlFormItemGroupVertical(params ControlFormItem[] items) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { - var grpupContex = new RenderContextFormularGroup(context, this); + var grpupContex = new RenderContextFormGroup(context, this); foreach (var item in Items) { @@ -55,9 +55,9 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { - var renderContext = new RenderContextFormularGroup(context, this); + var renderContext = new RenderContextFormGroup(context, this); var html = new HtmlElementTextContentDiv() { @@ -79,7 +79,7 @@ public override IHtmlNode Render(RenderContextFormular context) help.Initialize(renderContext); label.Text = context.I18N(input?.Label); - label.FormularItem = item; + label.FormItem = item; help.Text = context.I18N(input?.Help); if (icon.Icon != null) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs index 7145d08e..3b599df4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs @@ -20,7 +20,7 @@ public PropertySizeText Size public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemHelpText(string id) @@ -29,7 +29,7 @@ public ControlFormItemHelpText(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. @@ -43,7 +43,7 @@ public ControlFormItemHelpText(string id, string text) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { TextColor = new PropertyColorText(TypeColorText.Muted); } @@ -53,7 +53,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { return new HtmlElementTextSemanticsSmall() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs index a92a47e3..7156f4cb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebControl /// /// Identifies a control that is to be filled in by the user. /// - public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormularValidation + public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation { /// /// Event to validate the input values. @@ -91,7 +91,7 @@ public virtual TypesInputValidity ValidationResult public virtual string Value { get; set; } = string.Empty; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInput(string id) @@ -114,7 +114,7 @@ private void Init() /// Initializes the form.emement /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { } @@ -131,7 +131,7 @@ protected virtual void OnValidation(ValidationEventArgs e) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public virtual void Validate(RenderContextFormular context) + public virtual void Validate(RenderContextForm context) { IsValidated = true; diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs index 41faa3e1..5bea4d55 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs @@ -22,7 +22,7 @@ public class ControlFormItemInputCheckbox : ControlFormItemInput public string Pattern { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. public ControlFormItemInputCheckbox(string id = null) @@ -35,7 +35,7 @@ public ControlFormItemInputCheckbox(string id = null) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { var value = context.Request.GetParameter(Name)?.Value; @@ -47,7 +47,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var html = new HtmlElementTextContentDiv ( @@ -79,7 +79,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs index d80f64ab..cb355baa 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs @@ -28,7 +28,7 @@ public class ControlFormItemInputComboBox : ControlFormItemInput //public string SelectedValue { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputComboBox(string id = null) @@ -38,7 +38,7 @@ public ControlFormItemInputComboBox(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The ComboBox entries. @@ -49,7 +49,7 @@ public ControlFormItemInputComboBox(string id, params string[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The ComboBox entries. @@ -60,7 +60,7 @@ public ControlFormItemInputComboBox(string id, params ControlFormItemInputComboB } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The ComboBox entries. @@ -74,7 +74,7 @@ public ControlFormItemInputComboBox(string id, string name, IEnumerable /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { Value = context.Request.GetParameter(Name)?.Value; } @@ -84,7 +84,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var html = new HtmlElementFieldSelect() { @@ -120,7 +120,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs index 9272c9ec..8cc41d0e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs @@ -22,7 +22,7 @@ public class ControlFormItemInputComboBoxItem public object Tag { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public ControlFormItemInputComboBoxItem() { @@ -30,7 +30,7 @@ public ControlFormItemInputComboBoxItem() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The child entries. public ControlFormItemInputComboBoxItem(params ControlFormItemInputComboBoxItem[] subitems) @@ -40,7 +40,7 @@ public ControlFormItemInputComboBoxItem(params ControlFormItemInputComboBoxItem[ } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The child entries. public ControlFormItemInputComboBoxItem(IEnumerable subitems) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs index cb2ebbf1..1c8d1955 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs @@ -42,7 +42,7 @@ public class ControlFormItemInputDatepicker : ControlFormItemInput //public string InitializeCode => "$('#" + Id + " input').datepicker({ startDate: -3 });"; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputDatepicker(string id = null) @@ -54,7 +54,7 @@ public ControlFormItemInputDatepicker(string id = null) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { AutoInitialize = true; @@ -76,7 +76,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { @@ -124,7 +124,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs index 74d3393b..20e1f3bc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs @@ -26,7 +26,7 @@ public class ControlFormItemInputFile : ControlFormItemInput public ICollection AcceptFile { get; set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputFile(string id = null) @@ -37,7 +37,7 @@ public ControlFormItemInputFile(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The name. @@ -51,7 +51,7 @@ public ControlFormItemInputFile(string id, string name) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { Value = context?.Request.GetParameter(Name)?.Value; } @@ -61,7 +61,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { switch (ValidationResult) { @@ -94,7 +94,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { if (Disabled) { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs index f0e4b219..54fb5ccb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs @@ -21,7 +21,7 @@ public class ControlFormItemInputGroup : ControlFormItemInput public override TypesInputValidity ValidationResult => Group != null ? Group.ValidationResult : TypesInputValidity.Default; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputGroup(string id = null) @@ -32,7 +32,7 @@ public ControlFormItemInputGroup(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The name. @@ -47,7 +47,7 @@ public ControlFormItemInputGroup(string id, ControlFormItemGroup group) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { if (Group != null) { @@ -60,7 +60,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { return Group?.Render(context); } @@ -69,7 +69,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { if (Disabled) { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs index be2d8c9b..aa058f16 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemInputHidden : ControlFormItemInput { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputHidden(string id = null) @@ -15,7 +15,7 @@ public ControlFormItemInputHidden(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The name. @@ -29,7 +29,7 @@ public ControlFormItemInputHidden(string id, string name) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { Value = context?.Request.GetParameter(Name)?.Value; } @@ -39,7 +39,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { return new HtmlElementFieldInput() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs index 7d59cafc..982a0aa7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs @@ -2,8 +2,8 @@ using System.Linq; using System.Text; using System.Text.Json; +using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; namespace WebExpress.WebUI.WebControl { @@ -25,7 +25,7 @@ public class ControlFormItemInputMove : ControlFormItemInput public string AvailableHeader { get; set; } = "webexpress.webui:form.selectionmove.available"; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputMove(string id = null) @@ -35,7 +35,7 @@ public ControlFormItemInputMove(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The entries. @@ -49,7 +49,7 @@ public ControlFormItemInputMove(string id, params ControlFormItemInputSelectionI /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { if (context.Request.HasParameter(Name)) { @@ -62,7 +62,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var classes = Classes.ToList(); @@ -96,7 +96,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } @@ -108,7 +108,7 @@ public override void Validate(RenderContextFormular context) /// The id of the control. /// The css classes that are assigned to the control. /// The javascript code. - protected virtual string GetScript(RenderContextFormular context, string id, string css) + protected virtual string GetScript(RenderContextForm context, string id, string css) { var settings = new { @@ -117,15 +117,15 @@ protected virtual string GetScript(RenderContextFormular context, string id, str CSS = css, Header = new { - Selected = I18N(context, SelectedHeader), - Available = I18N(context, AvailableHeader) + Selected = context.I18N(SelectedHeader), + Available = context.I18N(AvailableHeader) }, Buttons = new { - ToSelectedAll = I18N(context, "Λ‚Λ‚"), - ToSelected = I18N(context, "Λ‚"), - ToAvailableAll = I18N(context, "ΛƒΛƒ"), - ToAvailable = I18N(context, "Λƒ") + ToSelectedAll = context.I18N("Λ‚Λ‚"), + ToSelected = context.I18N("Λ‚"), + ToAvailableAll = context.I18N("ΛƒΛƒ"), + ToAvailable = context.I18N("Λƒ") } }; diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs index 68e64534..21fbe7b2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs @@ -32,7 +32,7 @@ public class ControlFormItemInputRadio : ControlFormItemInput public bool Checked { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputRadio(string id = null) @@ -42,7 +42,7 @@ public ControlFormItemInputRadio(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The name. @@ -56,7 +56,7 @@ public ControlFormItemInputRadio(string id, string name) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { } @@ -65,7 +65,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { if (!string.IsNullOrWhiteSpace(Value)) { @@ -120,7 +120,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs index 0a169636..96232fa0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs @@ -40,7 +40,7 @@ public class ControlFormItemInputSelection : ControlFormItemInput public virtual ICollection Values => base.Value != null ? base.Value.Split(';', System.StringSplitOptions.RemoveEmptyEntries) : []; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputSelection(string id = null) @@ -50,7 +50,7 @@ public ControlFormItemInputSelection(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The entries. @@ -64,7 +64,7 @@ public ControlFormItemInputSelection(string id, params ControlFormItemInputSelec /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { if (context.Request.HasParameter(Name)) { @@ -77,7 +77,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var classes = Classes.ToList(); @@ -111,7 +111,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); } @@ -123,7 +123,7 @@ public override void Validate(RenderContextFormular context) /// The ID of the control. /// The CSS classes that are assigned to the control. /// The javascript code. - protected virtual string GetScript(RenderContextFormular context, string id, string css) + protected virtual string GetScript(RenderContextForm context, string id, string css) { var settings = new { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs index 6c8d7519..830c0fcc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs @@ -55,7 +55,7 @@ public class ControlFormItemInputTextBox : ControlFormItemInput public int Rows { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemInputTextBox(string id = null) @@ -66,7 +66,7 @@ public ControlFormItemInputTextBox(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The name of the text box. @@ -80,7 +80,7 @@ public ControlFormItemInputTextBox(string id, string name) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { base.Initialize(context); @@ -105,7 +105,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var id = Id ?? Guid.NewGuid().ToString(); @@ -182,7 +182,7 @@ public override IHtmlNode Render(RenderContextFormular context) /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - public override void Validate(RenderContextFormular context) + public override void Validate(RenderContextForm context) { base.Validate(context); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs index 7a5773e1..97d0f287 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs @@ -13,10 +13,10 @@ public class ControlFormItemLabel : ControlFormItem /// /// Returns or sets the associated form field. /// - public ControlFormItem FormularItem { get; set; } + public ControlFormItem FormItem { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemLabel(string id) @@ -25,7 +25,7 @@ public ControlFormItemLabel(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. @@ -39,7 +39,7 @@ public ControlFormItemLabel(string id, string text) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { } @@ -48,7 +48,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { return new HtmlElementFieldLabel() { @@ -56,10 +56,10 @@ public override IHtmlNode Render(RenderContextFormular context) Class = GetClasses(), Style = GetStyles(), Role = Role, - For = FormularItem != null ? - string.IsNullOrWhiteSpace(FormularItem.Id) ? - FormularItem.Name : - FormularItem.Id : + For = FormItem != null ? + string.IsNullOrWhiteSpace(FormItem.Id) ? + FormItem.Name : + FormItem.Id : null }; } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs index 0ec04125..bc8648bd 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs @@ -30,7 +30,7 @@ public TypePanelContainer Fluid } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemPanel(string id) @@ -39,7 +39,7 @@ public ControlFormItemPanel(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -52,7 +52,7 @@ public ControlFormItemPanel(string id, IEnumerable content) /// /// Initialization /// - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { } @@ -61,7 +61,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs index b6d449dd..ca4c3370 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebControl public class ControlFormItemPrepend : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemPrepend(string id) @@ -17,7 +17,7 @@ public ControlFormItemPrepend(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -28,7 +28,7 @@ public ControlFormItemPrepend(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -39,7 +39,7 @@ public ControlFormItemPrepend(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs index ec28ecdf..145cb57e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs @@ -17,7 +17,7 @@ public class ControlFormItemStaticText : ControlFormItem, IControlFormLabel public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlFormItemStaticText(string id = null) @@ -29,7 +29,7 @@ public ControlFormItemStaticText(string id = null) /// Initializes the form element. /// /// The context in which the control is rendered. - public override void Initialize(RenderContextFormular context) + public override void Initialize(RenderContextForm context) { } @@ -38,7 +38,7 @@ public override void Initialize(RenderContextFormular context) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContextFormular context) + public override IHtmlNode Render(RenderContextForm context) { var c = new List { diff --git a/src/WebExpress.WebUI/WebControl/ControlHtml.cs b/src/WebExpress.WebUI/WebControl/ControlHtml.cs index e6e6a930..942b4b90 100644 --- a/src/WebExpress.WebUI/WebControl/ControlHtml.cs +++ b/src/WebExpress.WebUI/WebControl/ControlHtml.cs @@ -11,7 +11,7 @@ public class ControlHtml : Control public string Html { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlHtml(string id = null) @@ -21,7 +21,7 @@ public ControlHtml(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. diff --git a/src/WebExpress.WebUI/WebControl/ControlIcon.cs b/src/WebExpress.WebUI/WebControl/ControlIcon.cs index eb21d6bd..48e987bb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlIcon.cs +++ b/src/WebExpress.WebUI/WebControl/ControlIcon.cs @@ -38,7 +38,7 @@ public PropertySizeText Size } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlIcon(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlImage.cs b/src/WebExpress.WebUI/WebControl/ControlImage.cs index 8e0c6268..08ce6b3a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlImage.cs +++ b/src/WebExpress.WebUI/WebControl/ControlImage.cs @@ -26,7 +26,7 @@ public class ControlImage : Control public string Tooltip { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlImage(string id = null) @@ -35,7 +35,7 @@ public ControlImage(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The image source. diff --git a/src/WebExpress.WebUI/WebControl/ControlLine.cs b/src/WebExpress.WebUI/WebControl/ControlLine.cs index 2f9b6a97..179b9289 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLine.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLine.cs @@ -25,7 +25,7 @@ public PropertyColorLine Color } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlLine(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index 951fe852..46e21214 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -91,7 +91,7 @@ public PropertySizeText Size } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlLink(string id = null) @@ -101,7 +101,7 @@ public ControlLink(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -112,7 +112,7 @@ public ControlLink(string id, string text) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlLink(params Control[] content) @@ -122,7 +122,7 @@ public ControlLink(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -133,7 +133,7 @@ public ControlLink(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -229,9 +229,9 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormularCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) diff --git a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs index 6cb0998b..cc87f0a8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs @@ -32,7 +32,7 @@ public class ControlLinkList : Control public List Links { get; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlLinkList(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index b7cb09f1..10de6f21 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -35,7 +35,7 @@ public TypeLayoutList Layout public bool ShowBorder { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlList(string id = null) @@ -45,7 +45,7 @@ public ControlList(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The list entries. @@ -56,7 +56,7 @@ public ControlList(string id, params ControlListItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The list entries. public ControlList(params ControlListItem[] items) @@ -65,7 +65,7 @@ public ControlList(params ControlListItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The list entries. @@ -76,7 +76,7 @@ public ControlList(string id, IEnumerable items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The list entries. public ControlList(IEnumerable items) diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index bde2b6a9..c141a7c6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -22,7 +22,7 @@ public TypeActive Active } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlListItem(string id = null) @@ -32,7 +32,7 @@ public ControlListItem(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -43,7 +43,7 @@ public ControlListItem(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItem(params Control[] content) @@ -52,7 +52,7 @@ public ControlListItem(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -65,7 +65,7 @@ public ControlListItem(string id, List content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItem(List content) diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs index 34432721..c4774e5a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.WebControl public class ControlListItemButton : ControlListItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlListItemButton(string id = null) @@ -18,7 +18,7 @@ public ControlListItemButton(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -29,7 +29,7 @@ public ControlListItemButton(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItemButton(params Control[] content) @@ -39,7 +39,7 @@ public ControlListItemButton(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -50,7 +50,7 @@ public ControlListItemButton(string id, List content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItemButton(List content) diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs index 204f8875..2fa2e8dc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs @@ -45,7 +45,7 @@ public class ControlListItemLink : ControlListItem public List Params { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlListItemLink(string id = null) @@ -55,7 +55,7 @@ public ControlListItemLink(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -66,7 +66,7 @@ public ControlListItemLink(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItemLink(params Control[] content) @@ -76,7 +76,7 @@ public ControlListItemLink(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -87,7 +87,7 @@ public ControlListItemLink(string id, List content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlListItemLink(List content) diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index b8daf96f..8d22de64 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -39,7 +39,7 @@ public class ControlModal : Control public string OnHiddenCode { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlModal(string id) @@ -49,7 +49,7 @@ public ControlModal(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The headline. @@ -60,7 +60,7 @@ public ControlModal(string id, string header) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The headline. @@ -75,7 +75,7 @@ public ControlModal(string id, string header, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. @@ -87,7 +87,7 @@ public ControlModal(string id, string text, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. diff --git a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs similarity index 76% rename from src/WebExpress.WebUI/WebControl/ControlModalFormular.cs rename to src/WebExpress.WebUI/WebControl/ControlModalForm.cs index fb3b8d63..c89cfccf 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalFormular.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs @@ -6,57 +6,57 @@ namespace WebExpress.WebUI.WebControl { - public class ControlModalFormular : ControlModal + public class ControlModalForm : ControlModal { /// - /// Returns the form + /// Returns the form. /// - public ControlForm Formular { get; private set; } + public ControlForm Form { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. - public ControlModalFormular(string id = null) + public ControlModalForm(string id = null) : this(id, string.Empty, null) { } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The headline. - public ControlModalFormular(string id, string header) + public ControlModalForm(string id, string header) : this(id, header, null) { } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The form controls. - public ControlModalFormular(string id, params ControlFormItem[] content) + public ControlModalForm(string id, params ControlFormItem[] content) : this(id, string.Empty, content) { } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The headline. /// The form controls. - public ControlModalFormular(string id, string header, params ControlFormItem[] content) + public ControlModalForm(string id, string header, params ControlFormItem[] content) : base("modal_" + id, string.Empty, null) { - Formular = content != null ? new ControlForm(id, content) : new ControlForm(id); - Formular.InitializeFormular += OnInitializeFormular; - Formular.Validated += OnValidatedFormular; + Form = content != null ? new ControlForm(id, content) : new ControlForm(id); + Form.InitializeForm += OnInitializeForm; + Form.Validated += OnValidatedForm; Header = header; } @@ -66,7 +66,7 @@ public ControlModalFormular(string id, string header, params ControlFormItem[] c /// The form item. public void Add(params ControlFormItem[] item) { - Formular.Add(item); + Form.Add(item); } /// @@ -75,7 +75,7 @@ public void Add(params ControlFormItem[] item) /// The form item. public void Remove(ControlFormItem item) { - Formular.Remove(item); + Form.Remove(item); } /// @@ -83,7 +83,7 @@ public void Remove(ControlFormItem item) /// /// The sender. /// The event argument. - private void OnInitializeFormular(object sender, FormularEventArgs e) + private void OnInitializeForm(object sender, FormEventArgs e) { ShowIfCreated = false; } @@ -93,7 +93,7 @@ private void OnInitializeFormular(object sender, FormularEventArgs e) /// /// The sender. /// The event argument. - private void OnValidatedFormular(object sender, ValidationResultEventArgs e) + private void OnValidatedForm(object sender, ValidationResultEventArgs e) { if (!e.Valid) { @@ -109,21 +109,21 @@ private void OnValidatedFormular(object sender, ValidationResultEventArgs e) /// The control as html. public override IHtmlNode Render(RenderContext context) { - return Render(context, Formular.Items); + return Render(context, Form.Items); } /// /// Convert to html. /// /// The context in which the control is rendered. - /// The formular items. + /// The form items. /// The control as html. public virtual IHtmlNode Render(RenderContext context, IEnumerable items) { var fade = Fade; var classes = Classes.ToList(); - var form = Formular.Render(context, items) as HtmlElementFormForm; + var form = Form.Render(context, items) as HtmlElementFormForm; classes.Add("modal"); @@ -158,17 +158,7 @@ public virtual IHtmlNode Render(RenderContext context, IEnumerable Items { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlMultipleProgressBar(string id = null) @@ -28,7 +28,7 @@ public ControlMultipleProgressBar(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The value. diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs index 1d038d19..726fca07 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs @@ -63,7 +63,7 @@ public TypeOrientationTab Orientation public List Items { get; private set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlNavigation(string id = null) @@ -73,7 +73,7 @@ public ControlNavigation(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The navigation items. public ControlNavigation(params IControlNavigationItem[] items) @@ -85,7 +85,7 @@ public ControlNavigation(params IControlNavigationItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -98,7 +98,7 @@ public ControlNavigation(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlNavigation(IEnumerable content) diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs index d3616f93..da7bfadc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebControl public class ControlNavigationItemDropdown : ControlDropdown, IControlNavigationItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlNavigationItemDropdown(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs index 429848a3..a9376e4c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs @@ -12,7 +12,7 @@ public class ControlNavigationItemHeader : Control, IControlNavigationItem public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlNavigationItemHeader(string id = null) @@ -21,7 +21,7 @@ public ControlNavigationItemHeader(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs index 71197977..2b68561e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs @@ -11,7 +11,7 @@ public class ControlNavigationItemLink : ControlLink, IControlNavigationItem public bool NoWrap { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlNavigationItemLink(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlPagination.cs b/src/WebExpress.WebUI/WebControl/ControlPagination.cs index 2a988f2a..d795f4d2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPagination.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPagination.cs @@ -38,7 +38,7 @@ public TypeSizePagination Size } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPagination(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index edac0b32..084bb0a0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -31,7 +31,7 @@ public TypePanelContainer Fluid } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanel(string id = null) @@ -40,7 +40,7 @@ public ControlPanel(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlPanel(params IControl[] content) @@ -50,7 +50,7 @@ public ControlPanel(params IControl[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlPanel(ICollection content) @@ -60,7 +60,7 @@ public ControlPanel(ICollection content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -71,7 +71,7 @@ public ControlPanel(string id, params IControl[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -82,7 +82,7 @@ public ControlPanel(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs index 8dad3657..8d92633c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs @@ -21,7 +21,7 @@ public PropertyColorCallout Color } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelCallout(string id = null) @@ -30,7 +30,7 @@ public ControlPanelCallout(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlPanelCallout(params Control[] content) @@ -40,7 +40,7 @@ public ControlPanelCallout(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs index 43fd129a..a2e43f9c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs @@ -37,7 +37,7 @@ public class ControlPanelCard : ControlPanel public string FooterImage { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelCard(string id = null) @@ -47,7 +47,7 @@ public ControlPanelCard(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelCard(string id, params Control[] items) @@ -57,7 +57,7 @@ public ControlPanelCard(string id, params Control[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The controls to insert. public ControlPanelCard(params Control[] items) @@ -100,7 +100,7 @@ public override IHtmlNode Render(RenderContext context) if (!string.IsNullOrWhiteSpace(Header)) { - html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(InternationalizationManager.I18N(context, Header))) { Class = "card-header" }); + html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(context.I18N(Header))) { Class = "card-header" }); } if (!string.IsNullOrWhiteSpace(HeaderImage)) @@ -116,8 +116,8 @@ public override IHtmlNode Render(RenderContext context) { Content.Insert(0, new ControlText() { - Text = InternationalizationManager.I18N(context, Headline), - Classes = new List(new[] { "card-title" }), + Text = context.I18N(Headline), + Classes = new List(["card-title"]), Format = TypeFormatText.H4 }); } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs index debee75c..2ee5f844 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebControl public class ControlPanelCenter : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelCenter(string id = null) @@ -17,7 +17,7 @@ public ControlPanelCenter(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlPanelCenter(params Control[] content) @@ -27,7 +27,7 @@ public ControlPanelCenter(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs b/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs index 1383190f..86364ca9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs @@ -3,7 +3,7 @@ public class ControlPanelDialog : ControlForm { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelDialog(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs index 79ea76bf..51fe0352 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs @@ -3,7 +3,7 @@ public class ControlPanelFilter : ControlForm { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelFilter(string id = null) @@ -17,7 +17,6 @@ public ControlPanelFilter(string id = null) /// private void Init() { - SubmitButton.Text = "Update"; } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs index 6da6d4bb..cf4280fa 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs @@ -44,7 +44,7 @@ public virtual TypeWrap Wrap } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelFlexbox(string id = null) @@ -53,7 +53,7 @@ public ControlPanelFlexbox(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The flexbox items. @@ -63,7 +63,7 @@ public ControlPanelFlexbox(string id, params IControl[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The flexbox items. public ControlPanelFlexbox(params IControl[] content) @@ -72,7 +72,7 @@ public ControlPanelFlexbox(params IControl[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The flexbox items. @@ -82,7 +82,7 @@ public ControlPanelFlexbox(string id, IEnumerable content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The flexbox items. public ControlPanelFlexbox(IEnumerable content) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs index d7f42e87..cd9ee807 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.WebControl public class ControlPanelFooter : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelFooter(string id = null) @@ -18,7 +18,7 @@ public ControlPanelFooter(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -29,7 +29,7 @@ public ControlPanelFooter(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs index d3aa369d..6826970a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebControl public class ControlPanelGrid : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelGrid(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs index 9aa3a5d6..45f8da2c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs @@ -25,7 +25,7 @@ public virtual TypeSticky Sticky } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelHeader(string id = null) @@ -35,7 +35,7 @@ public ControlPanelHeader(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlPanelHeader(params Control[] content) @@ -45,7 +45,7 @@ public ControlPanelHeader(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs index 3671a0f4..10ec29cb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebControl public class ControlPanelMain : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelMain(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs index c9a20dd8..17f5ebdb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs @@ -27,7 +27,7 @@ public class ControlPanelMedia : ControlPanel public int ImageHeight { get; set; } = -1; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelMedia(string id = null) @@ -37,7 +37,7 @@ public ControlPanelMedia(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The headline. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs index 5ccfffc5..356df643 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebControl public class ControlPanelNavbar : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelNavbar(string id = null) @@ -17,7 +17,7 @@ public ControlPanelNavbar(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The navbar items. @@ -28,7 +28,7 @@ public ControlPanelNavbar(string id, params Control[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The navbar items. public ControlPanelNavbar(params Control[] items) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs index e3481daf..f1b2406d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs @@ -58,7 +58,7 @@ public class ControlPanelSplit : Control public int Panel2InitialSize { get; set; } = -1; /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelSplit(string id = null) @@ -67,7 +67,7 @@ public ControlPanelSplit(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// Left or top panel controls. @@ -80,7 +80,7 @@ public ControlPanelSplit(string id, Control[] panel1, Control[] panel2) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Left or top panel controls. /// Right or bottom panel controls. diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs index 97288653..3d8af878 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs @@ -3,7 +3,7 @@ public class ControlPanelToast : ControlPanel { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelToast(string id) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs index 0f2080e6..84d4599d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs @@ -15,7 +15,7 @@ public class ControlPanelTool : ControlPanel public ControlDropdown Tools { get; } = new ControlDropdown(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelTool(string id = null) @@ -25,7 +25,7 @@ public ControlPanelTool(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelTool(string id, params Control[] items) @@ -35,7 +35,7 @@ public ControlPanelTool(string id, params Control[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlPanelTool(params Control[] items) diff --git a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs index 908cf07c..ce0d98a6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs @@ -50,7 +50,7 @@ public TypeSizeProgress Size public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlProgressBar(string id = null) @@ -60,7 +60,7 @@ public ControlProgressBar(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The value. @@ -71,7 +71,7 @@ public ControlProgressBar(string id, int value) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The value. diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs index b2b3d3a4..1301e839 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs @@ -75,7 +75,7 @@ public TypeActive Active protected List Items { get; private set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlSplitButton(string id = null) @@ -85,7 +85,7 @@ public ControlSplitButton(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlSplitButton(params IControlSplitButtonItem[] items) @@ -97,7 +97,7 @@ public ControlSplitButton(params IControlSplitButtonItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -110,7 +110,7 @@ public ControlSplitButton(string id, params IControlSplitButtonItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -123,7 +123,7 @@ public ControlSplitButton(string id, IEnumerable items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlSplitButton(IEnumerable items) @@ -182,7 +182,7 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs index 16efe251..f8a5daca 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebControl public class ControlSplitButtonItemDivider : Control, IControlSplitButtonItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlSplitButtonItemDivider(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs index 89e93aa0..c024ad70 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs @@ -11,7 +11,7 @@ public class ControlSplitButtonItemHeader : Control, IControlSplitButtonItem public string Text { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlSplitButtonItemHeader(string id = null) @@ -21,7 +21,7 @@ public ControlSplitButtonItemHeader(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The text. diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs index 9092c037..b8736d21 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs @@ -6,7 +6,7 @@ namespace WebExpress.WebUI.WebControl public class ControlSplitButtonItemLink : ControlLink, IControlSplitButtonItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlSplitButtonItemLink(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs index 7121e240..a251dbe6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs @@ -19,7 +19,7 @@ public class ControlSplitButtonLink : ControlSplitButton public string Uri { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlSplitButtonLink(string id) @@ -29,7 +29,7 @@ public ControlSplitButtonLink(string id) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -42,7 +42,7 @@ public ControlSplitButtonLink(string id, params IControlSplitButtonItem[] conten } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlSplitButtonLink(params IControlSplitButtonItem[] content) @@ -54,7 +54,7 @@ public ControlSplitButtonLink(params IControlSplitButtonItem[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. @@ -67,7 +67,7 @@ public ControlSplitButtonLink(string id, IEnumerable co } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// The content of the html element. @@ -165,9 +165,9 @@ public override IHtmlNode Render(RenderContext context) { } - else if (Modal.Type == TypeModal.Formular) + else if (Modal.Type == TypeModal.Form) { - button.OnClick = $"new webexpress.webui.modalFormularCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; button.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) diff --git a/src/WebExpress.WebUI/WebControl/ControlTable.cs b/src/WebExpress.WebUI/WebControl/ControlTable.cs index 93e71839..442ae586 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTable.cs @@ -38,7 +38,7 @@ public class ControlTable : Control public bool Reflow { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTable(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs index 81782091..f02f5110 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs @@ -26,7 +26,7 @@ public class ControlTableColumn : Control public PropertyIcon Icon { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTableColumn(string id) diff --git a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs index 480e2a06..82ae554a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs @@ -21,7 +21,7 @@ public class ControlTableRow : Control public List Cells { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTableRow(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlTableSortable.cs b/src/WebExpress.WebUI/WebControl/ControlTableSortable.cs index 02d4f2b4..51f391b9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableSortable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableSortable.cs @@ -26,7 +26,7 @@ // } // /// - // /// Constructor + // /// Initializes a new instance of the class. // /// // /// The page id. // /// The id. diff --git a/src/WebExpress.WebUI/WebControl/ControlTag.cs b/src/WebExpress.WebUI/WebControl/ControlTag.cs index cab9801c..023b7799 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTag.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTag.cs @@ -28,7 +28,7 @@ public class ControlTag : Control protected List Items { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTag(string id = null) @@ -38,7 +38,7 @@ public ControlTag(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -49,7 +49,7 @@ public ControlTag(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. diff --git a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs index efe16d36..8ca8e5ff 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs @@ -12,7 +12,7 @@ public class ControlTagCloud : Control public Uri Uri { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTagCloud(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlText.cs b/src/WebExpress.WebUI/WebControl/ControlText.cs index a16ae4ef..6426caff 100644 --- a/src/WebExpress.WebUI/WebControl/ControlText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlText.cs @@ -40,7 +40,7 @@ public PropertySizeText Size public string Title { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public ControlText() : base(null) @@ -48,7 +48,7 @@ public ControlText() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlText(string id) diff --git a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs index 6c784af2..7022fe1a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs @@ -16,7 +16,7 @@ public class ControlTimeline : Control public List Items { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTimeline(string id = null) @@ -26,7 +26,7 @@ public ControlTimeline(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTimeline(params ControlTimelineItem[] items) diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs index 0df8f304..b3dfb4f3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs @@ -32,7 +32,7 @@ public class ControlTimelineComment : Control public int Likes { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTimelineComment(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs index 22d8bbc6..946de925 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs @@ -49,7 +49,7 @@ public class ControlTimelineItem : Control public int Likes { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTimelineItem(string id = null) @@ -191,11 +191,12 @@ public override IHtmlNode Render(RenderContext context) Name = !string.IsNullOrWhiteSpace(Name) ? Name : "form" }; - form.SubmitButton.Icon = new PropertyIcon(TypeIcon.PaperPlane); - form.SubmitButton.Text = "Antworten"; - form.SubmitButton.Outline = true; - form.SubmitButton.Size = TypeSizeButton.Small; - //form.SubmitButton.HorizontalAlignment = TypeHorizontalAlignment.Default; + form.AddPrimaryButton(new ControlFormItemButtonSubmit("") + { + Icon = new PropertyIcon(TypeIcon.PaperPlane), + Outline = true, + Size = TypeSizeButton.Small + }); form.Add(new ControlFormItemInputTextBox() { Format = TypesEditTextFormat.Multiline, Placeholder = "Kommentieren..." }); diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs index cc4fe6b1..5d377767 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs @@ -40,7 +40,7 @@ public virtual TypeSticky Sticky public List Items { get; private set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlToolbar(string id = null) @@ -50,7 +50,7 @@ public ControlToolbar(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// Die Toolitems @@ -61,7 +61,7 @@ public ControlToolbar(string id = null, params IControlToolBarItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Toolitems public ControlToolbar(params IControlToolBarItem[] items) diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs index c35814fd..4895d228 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs @@ -3,7 +3,7 @@ public class ControlToolBarItemButton : ControlLink, IControlToolBarItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlToolBarItemButton(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs index 5da587b9..37af56e4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs @@ -3,7 +3,7 @@ public class ControlToolBarItemSeperator : ControlLine, IControlToolBarItem { /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlToolBarItemSeperator(string id = null) diff --git a/src/WebExpress.WebUI/WebControl/ControlTree.cs b/src/WebExpress.WebUI/WebControl/ControlTree.cs index 995e1414..0a1f3d3a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTree.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTree.cs @@ -32,7 +32,7 @@ public TypeLayoutTree Layout public bool ShowBorder { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTree(string id = null) @@ -42,7 +42,7 @@ public ControlTree(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// Die ListeneintrΓ€ge @@ -53,7 +53,7 @@ public ControlTree(string id, params ControlTreeItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die ListeneintrΓ€ge public ControlTree(params ControlTreeItem[] items) @@ -62,7 +62,7 @@ public ControlTree(params ControlTreeItem[] items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id. /// Die ListeneintrΓ€ge @@ -73,7 +73,7 @@ public ControlTree(string id, List items) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die ListeneintrΓ€ge public ControlTree(List items) diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs index b7c248ea..78fe4310 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs @@ -58,7 +58,7 @@ public TypeExpandTree Expand } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTreeItem(string id = null) @@ -68,7 +68,7 @@ public ControlTreeItem(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -80,7 +80,7 @@ public ControlTreeItem(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlTreeItem(params Control[] content) @@ -89,7 +89,7 @@ public ControlTreeItem(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -99,7 +99,7 @@ public ControlTreeItem(string id, List content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlTreeItem(List content) diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs index c671cc0c..47283c4e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs @@ -45,7 +45,7 @@ public class ControlTreeItemLink : ControlTreeItem /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. public ControlTreeItemLink(string id = null) @@ -55,7 +55,7 @@ public ControlTreeItemLink(string id = null) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -66,7 +66,7 @@ public ControlTreeItemLink(string id, params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlTreeItemLink(params Control[] content) @@ -76,7 +76,7 @@ public ControlTreeItemLink(params Control[] content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. @@ -87,7 +87,7 @@ public ControlTreeItemLink(string id, List content) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The content of the html element. public ControlTreeItemLink(List content) diff --git a/src/WebExpress.WebUI/WebControl/FormEventArgs.cs b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs new file mode 100644 index 00000000..493f8feb --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs @@ -0,0 +1,22 @@ +ο»Ώusing System; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Event argument for forms. + /// + public class FormEventArgs : EventArgs + { + /// + /// The form context. + /// + public RenderContextForm Context { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public FormEventArgs() + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/FormularEventArgs.cs b/src/WebExpress.WebUI/WebControl/FormularEventArgs.cs deleted file mode 100644 index 280b800a..00000000 --- a/src/WebExpress.WebUI/WebControl/FormularEventArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -ο»Ώusing System; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Eventargument fΓΌr Formulare - /// - public class FormularEventArgs : EventArgs - { - /// - /// Der Formular-Kontext - /// - public RenderContextFormular Context { get; set; } - - /// - /// Constructor - /// - public FormularEventArgs() - { - } - } -} diff --git a/src/WebExpress.WebUI/WebControl/IControlForm.cs b/src/WebExpress.WebUI/WebControl/IControlForm.cs index b18bead9..53a2e5ae 100644 --- a/src/WebExpress.WebUI/WebControl/IControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/IControlForm.cs @@ -14,22 +14,22 @@ public interface IControlForm : IControl /// /// Event is raised when the form has been initialized. /// - event EventHandler InitializeFormular; + event EventHandler InitializeForm; /// /// Event is raised when the form's data needs to be determined. /// - event EventHandler FillFormular; + event EventHandler FillForm; /// /// Event is raised when the form is about to be processed. /// - event EventHandler ProcessFormular; + event EventHandler ProcessForm; /// /// Event is raised when the form is to be processed and the next data is to be loaded. /// - event EventHandler ProcessAndNextFormular; + event EventHandler ProcessAndNextForm; /// /// Returns or sets the name of the form. @@ -46,11 +46,6 @@ public interface IControlForm : IControl /// string RedirectUri { get; set; } - /// - /// Returns or sets the submit button. - /// - ControlFormItemButton SubmitButton { get; } - /// /// Returns or sets the form items. /// @@ -65,13 +60,13 @@ public interface IControlForm : IControl /// Initializes the form. /// /// The context in which the control is rendered. - void Initialize(RenderContextFormular context); + void Initialize(RenderContextForm context); /// /// Pre-processes the form. /// /// The context in which the control is rendered. - void PreProcess(RenderContextFormular context); + void PreProcess(RenderContextForm context); /// /// Adds form control items to the form. @@ -90,6 +85,6 @@ public interface IControlForm : IControl /// /// The context in which the inputs are validated. /// True if all form items are valid, false otherwise. - bool Validate(RenderContextFormular context); + bool Validate(RenderContextForm context); } } diff --git a/src/WebExpress.WebUI/WebControl/IFormularValidation.cs b/src/WebExpress.WebUI/WebControl/IFormValidation.cs similarity index 88% rename from src/WebExpress.WebUI/WebControl/IFormularValidation.cs rename to src/WebExpress.WebUI/WebControl/IFormValidation.cs index d95d8aac..6366831c 100644 --- a/src/WebExpress.WebUI/WebControl/IFormularValidation.cs +++ b/src/WebExpress.WebUI/WebControl/IFormValidation.cs @@ -2,7 +2,7 @@ namespace WebExpress.WebUI.WebControl { - public interface IFormularValidation + public interface IFormValidation { /// /// Returns or sets whether the form element has been validated. @@ -23,6 +23,6 @@ public interface IFormularValidation /// Checks the input element for correctness of the data. /// /// The context in which the inputs are validated. - void Validate(RenderContextFormular context); + void Validate(RenderContextForm context); } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyBorder.cs b/src/WebExpress.WebUI/WebControl/PropertyBorder.cs index f8110b63..f82ecfdc 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyBorder.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyBorder.cs @@ -25,7 +25,7 @@ public class PropertyBorder : IProperty public bool Right { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyBorder() { @@ -33,7 +33,7 @@ public PropertyBorder() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Bestimmt, ob ein einheitlicher Rahmen angezeigt werden soll public PropertyBorder(bool showBorder = true) @@ -42,7 +42,7 @@ public PropertyBorder(bool showBorder = true) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der horzontale Rahmen /// Der vertikale Rahmen @@ -53,7 +53,7 @@ public PropertyBorder(bool horizontal, bool vertical) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der linke Rahmen /// Der rechte Rahmen diff --git a/src/WebExpress.WebUI/WebControl/PropertyColor.cs b/src/WebExpress.WebUI/WebControl/PropertyColor.cs index 3a3c94ff..ae8163fb 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColor.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColor.cs @@ -13,7 +13,7 @@ public abstract class PropertyColor : IProperty where T : System.Enum public string UserColor { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyColor() { diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs index e4af4d55..99792e87 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs @@ -3,7 +3,7 @@ public class PropertyColorBackground : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyColorBackground() { @@ -11,7 +11,7 @@ public PropertyColorBackground() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackground(TypeColorBackground color) @@ -20,7 +20,7 @@ public PropertyColorBackground(TypeColorBackground color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackground(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs index 4233f928..5c23992a 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs @@ -3,7 +3,7 @@ public class PropertyColorBackgroundAlert : PropertyColorBackground { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundAlert(TypeColorBackground color) @@ -12,7 +12,7 @@ public PropertyColorBackgroundAlert(TypeColorBackground color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundAlert(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs index 1afc259b..1b70f74d 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs @@ -3,7 +3,7 @@ public class PropertyColorBackgroundBadge : PropertyColorBackground { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundBadge(TypeColorBackground color) @@ -12,7 +12,7 @@ public PropertyColorBackgroundBadge(TypeColorBackground color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundBadge(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs index 7b22fcc6..2ad53f4a 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs @@ -3,7 +3,7 @@ public class PropertyColorBackgroundList : PropertyColorBackground { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundList(TypeColorBackground color) @@ -12,7 +12,7 @@ public PropertyColorBackgroundList(TypeColorBackground color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBackgroundList(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs index 0ed39134..7cf77755 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs @@ -3,7 +3,7 @@ public class PropertyColorBorder : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBorder(TypeColorBorder color) @@ -12,7 +12,7 @@ public PropertyColorBorder(TypeColorBorder color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorBorder(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs b/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs index eb1e8894..cb507080 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs @@ -3,7 +3,7 @@ public class PropertyColorButton : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorButton(TypeColorButton color) @@ -12,7 +12,7 @@ public PropertyColorButton(TypeColorButton color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorButton(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs b/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs index d1af8d02..1184d218 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs @@ -3,7 +3,7 @@ public class PropertyColorCallout : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorCallout(TypeColorCallout color) @@ -12,7 +12,7 @@ public PropertyColorCallout(TypeColorCallout color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorCallout(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs b/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs index c89cf74f..0cd60ac8 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs @@ -3,7 +3,7 @@ public class PropertyColorChart : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyColorChart() { @@ -11,7 +11,7 @@ public PropertyColorChart() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorChart(TypeColorChart color) @@ -20,7 +20,7 @@ public PropertyColorChart(TypeColorChart color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorChart(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs b/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs index 774da2b7..0fb649de 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs @@ -3,7 +3,7 @@ public class PropertyColorLine : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorLine(TypeColorLine color) @@ -12,7 +12,7 @@ public PropertyColorLine(TypeColorLine color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorLine(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs b/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs index 969c1fb5..16630a5e 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs @@ -3,7 +3,7 @@ public class PropertyColorNavbar : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorNavbar(TypeColorNavbar color) @@ -12,7 +12,7 @@ public PropertyColorNavbar(TypeColorNavbar color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorNavbar(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs b/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs index b645e889..24f29afe 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs @@ -3,7 +3,7 @@ public class PropertyColorProgress : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorProgress(TypeColorProgress color) @@ -12,7 +12,7 @@ public PropertyColorProgress(TypeColorProgress color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorProgress(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorText.cs b/src/WebExpress.WebUI/WebControl/PropertyColorText.cs index 3aec5a5a..e47e630d 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorText.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorText.cs @@ -3,7 +3,7 @@ public class PropertyColorText : PropertyColor { /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyColorText() { @@ -11,7 +11,7 @@ public PropertyColorText() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorText(TypeColorText color) @@ -20,7 +20,7 @@ public PropertyColorText(TypeColorText color) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Farbe public PropertyColorText(string color) diff --git a/src/WebExpress.WebUI/WebControl/PropertyGrid.cs b/src/WebExpress.WebUI/WebControl/PropertyGrid.cs index 768cc419..6dde8921 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyGrid.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyGrid.cs @@ -14,7 +14,7 @@ public class PropertyGrid : IProperty public int Columns { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertyGrid() { @@ -22,7 +22,7 @@ public PropertyGrid() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Bestimmt, ob ein einheitlicher Rahmen angezeigt werden soll /// Die Anzahl der verwendeten Spalten. Hinweis: Alle Spalten innerhalb eines PannelGrids muss die Summer 12 ergeben! diff --git a/src/WebExpress.WebUI/WebControl/PropertyIcon.cs b/src/WebExpress.WebUI/WebControl/PropertyIcon.cs index b6372878..cd584065 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyIcon.cs @@ -18,7 +18,7 @@ public class PropertyIcon : IProperty public PropertySizeIcon Size { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Das System-Icon public PropertyIcon(TypeIcon icon) @@ -27,7 +27,7 @@ public PropertyIcon(TypeIcon icon) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Das benutzerdefinierte Icon public PropertyIcon(string icon, PropertySizeIcon size = null) diff --git a/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs b/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs index 9bb21e8a..6cbf6987 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.WebControl public class PropertyMaxSizeIcon : PropertySizeIcon { /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Grâße /// Die Einheit @@ -15,7 +15,7 @@ public PropertyMaxSizeIcon(int size, TypeSizeUnit unit) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Weite in Pixel /// Die HΓΆhe in Pixel diff --git a/src/WebExpress.WebUI/WebControl/PropertyModal.cs b/src/WebExpress.WebUI/WebControl/PropertyModal.cs index 5e45a129..9a062644 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyModal.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyModal.cs @@ -28,7 +28,7 @@ public class PropertyModal public string RedirectUri { get; set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der Typ /// Das benutzerdefinierte Modal oder null @@ -41,7 +41,7 @@ public PropertyModal() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der Typ /// Die Grâße des Modals @@ -54,7 +54,7 @@ public PropertyModal(TypeModal type, TypeModalSize size = TypeModalSize.Default) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der Typ /// Das benutzerdefinierte Modal @@ -68,7 +68,7 @@ public PropertyModal(TypeModal type, ControlModal modal, TypeModalSize size = Ty } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der Typ /// Die Uri diff --git a/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs b/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs index 276a81ca..fb5a7e31 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs @@ -13,7 +13,7 @@ public class PropertyOnChange public string UserValue { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der System-Wert public PropertyOnChange(TypeOnChange value) @@ -22,7 +22,7 @@ public PropertyOnChange(TypeOnChange value) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der benutzerdefinierte Wert public PropertyOnChange(string value) diff --git a/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs b/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs index 9f23fdd7..364e0066 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs @@ -13,7 +13,7 @@ public class PropertyOnClick public string Value { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der benutzerdefinierte Wert public PropertyOnClick(string value) diff --git a/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs b/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs index ef0e2b16..ede77437 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs @@ -20,7 +20,7 @@ public class PropertySizeIcon : IProperty public int Height { get; protected set; } = -1; /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Grâße /// Die Einheit @@ -32,7 +32,7 @@ public PropertySizeIcon(int size, TypeSizeUnit unit) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die Weite in Pixel /// Die HΓΆhe in Pixel diff --git a/src/WebExpress.WebUI/WebControl/PropertySizeText.cs b/src/WebExpress.WebUI/WebControl/PropertySizeText.cs index 590668aa..5c952250 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySizeText.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySizeText.cs @@ -15,7 +15,7 @@ public class PropertySizeText : IProperty public float? UserSize { get; protected set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die System-Grâße public PropertySizeText(TypeSizeText size) @@ -24,7 +24,7 @@ public PropertySizeText(TypeSizeText size) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Das benutzerdefinierte Grâße in REM public PropertySizeText(float size) diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacing.cs b/src/WebExpress.WebUI/WebControl/PropertySpacing.cs index f83d909e..d9aa963f 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacing.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacing.cs @@ -28,7 +28,7 @@ public enum Space { None, Null, One, Two, Three, Four, Five, Auto }; public Space Right { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertySpacing() { @@ -36,7 +36,7 @@ public PropertySpacing() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die AbstΓ€nde public PropertySpacing(Space size) @@ -45,7 +45,7 @@ public PropertySpacing(Space size) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der horzontale Abstand /// Der vertikale Abstand @@ -56,7 +56,7 @@ public PropertySpacing(Space horizontal, Space vertical) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der linke Abstand /// Der rechte Abstand diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs b/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs index 9b301f98..baf14ac8 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs @@ -3,7 +3,7 @@ public class PropertySpacingMargin : PropertySpacing { /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertySpacingMargin() { @@ -11,7 +11,7 @@ public PropertySpacingMargin() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die AbstΓ€nde public PropertySpacingMargin(Space size) @@ -20,7 +20,7 @@ public PropertySpacingMargin(Space size) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der horzontale Abstand /// Der vertikale Abstand @@ -30,7 +30,7 @@ public PropertySpacingMargin(Space horizontal, Space vertical) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der linke Abstand /// Der rechte Abstand diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs b/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs index c02382e3..b7a48896 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs @@ -3,7 +3,7 @@ public class PropertySpacingPadding : PropertySpacing { /// - /// Constructor + /// Initializes a new instance of the class. /// public PropertySpacingPadding() { @@ -11,7 +11,7 @@ public PropertySpacingPadding() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Die AbstΓ€nde public PropertySpacingPadding(Space size) @@ -20,7 +20,7 @@ public PropertySpacingPadding(Space size) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der horzontale Abstand /// Der vertikale Abstand @@ -30,7 +30,7 @@ public PropertySpacingPadding(Space horizontal, Space vertical) } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der linke Abstand /// Der rechte Abstand diff --git a/src/WebExpress.WebUI/WebControl/RenderContextFormular.cs b/src/WebExpress.WebUI/WebControl/RenderContextForm.cs similarity index 71% rename from src/WebExpress.WebUI/WebControl/RenderContextFormular.cs rename to src/WebExpress.WebUI/WebControl/RenderContextForm.cs index af345760..51e1b6a0 100644 --- a/src/WebExpress.WebUI/WebControl/RenderContextFormular.cs +++ b/src/WebExpress.WebUI/WebControl/RenderContextForm.cs @@ -4,12 +4,12 @@ namespace WebExpress.WebUI.WebControl { - public class RenderContextFormular : RenderContext + public class RenderContextForm : RenderContext { /// /// The form in which the control is rendered. /// - public IControlForm Formular { get; private set; } + public IControlForm Form { get; private set; } /// /// Returns or sets the links to the java script files to be used. @@ -22,35 +22,35 @@ public class RenderContextFormular : RenderContext public ICollection ValidationResults { get; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// /// The page where the control is rendered. /// The request. /// The visual tree. - /// The form in which the control is rendered. - public RenderContextFormular(IPage page, Request request, IVisualTree visualTree, IControlForm formular) + /// The form in which the control is rendered. + public RenderContextForm(IPage page, Request request, IVisualTree visualTree, IControlForm form) : base(page, request, visualTree) { - Formular = formular; + Form = form; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The context in which the control is rendered. - /// The form in which the control is rendered. - public RenderContextFormular(RenderContext context, IControlForm formular) + /// The form in which the control is rendered. + public RenderContextForm(RenderContext context, IControlForm form) : base(context) { - Formular = formular; + Form = form; } /// /// Copy-Constructor /// /// The render context to copy./param> - public RenderContextFormular(RenderContextFormular context) - : this(context, context?.Formular) + public RenderContextForm(RenderContextForm context) + : this(context, context?.Form) { Scripts = context.Scripts; } diff --git a/src/WebExpress.WebUI/WebControl/RenderContextFormularGroup.cs b/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs similarity index 60% rename from src/WebExpress.WebUI/WebControl/RenderContextFormularGroup.cs rename to src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs index f2b272b9..393925f5 100644 --- a/src/WebExpress.WebUI/WebControl/RenderContextFormularGroup.cs +++ b/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs @@ -2,7 +2,7 @@ namespace WebExpress.WebUI.WebControl { - public class RenderContextFormularGroup : RenderContextFormular + public class RenderContextFormGroup : RenderContextForm { /// /// Die Gruppe, indem das Steuerelement gerendert wird @@ -10,22 +10,22 @@ public class RenderContextFormularGroup : RenderContextFormular public ControlFormItemGroup Group { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The context in which the control is rendered. - /// The form in which the control is rendered. + /// The form in which the control is rendered. /// Die Gruppe - public RenderContextFormularGroup(RenderContext context, ControlForm formular, ControlFormItemGroup group) - : base(context, formular) + public RenderContextFormGroup(RenderContext context, ControlForm form, ControlFormItemGroup group) + : base(context, form) { } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The context in which the control is rendered. /// Die Gruppe - public RenderContextFormularGroup(RenderContextFormular context, ControlFormItemGroup group) + public RenderContextFormGroup(RenderContextForm context, ControlFormItemGroup group) : base(context) { Group = group; diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs index 4d9c50df..39a41820 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs @@ -1,12 +1,11 @@ ο»Ώnamespace WebExpress.WebUI.WebControl { /// - /// The layout options of the forms. + /// The layout options of the form in relation to the elements. /// public enum TypeLayoutForm { - Vertical, - Horizontal, - Mix + Default, + Inline } } diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs new file mode 100644 index 00000000..1b1d569d --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs @@ -0,0 +1,12 @@ +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// The layout options of the items in a form. + /// + public enum TypeLayoutFormItem + { + Vertical, + Horizontal, + Mix + } +} diff --git a/src/WebExpress.WebUI/WebControl/TypeModal.cs b/src/WebExpress.WebUI/WebControl/TypeModal.cs index 15e4c028..c213c87e 100644 --- a/src/WebExpress.WebUI/WebControl/TypeModal.cs +++ b/src/WebExpress.WebUI/WebControl/TypeModal.cs @@ -6,7 +6,7 @@ public enum TypeModal { None, - Formular, + Form, Brwoser, Modal } diff --git a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs index cf1c0794..0261d058 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs @@ -3,22 +3,22 @@ namespace WebExpress.WebUI.WebControl { /// - /// Eventargument zum Validieren von Formulareingaben + /// Event argument for validating form inputs. /// - public class ValidationEventArgs : FormularEventArgs + public class ValidationEventArgs : FormEventArgs { /// - /// Liefert oder setzt sen zu ΓΌberprΓΌfenden Wert + /// Returns or sets the value to be checked. /// public string Value { get; set; } /// - /// Liefert oder setzt die Validierungsnachrichten + /// Returns or sets the validation results. /// public List Results { get; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// public ValidationEventArgs() { diff --git a/src/WebExpress.WebUI/WebControl/ValidationResult.cs b/src/WebExpress.WebUI/WebControl/ValidationResult.cs index d02b5f1f..ddf9384f 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationResult.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationResult.cs @@ -13,7 +13,7 @@ public class ValidationResult public string Text { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// Der Fehlertyp /// Der Fehlertext diff --git a/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs b/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs index bdf8a68b..2b25a87a 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs @@ -4,31 +4,31 @@ namespace WebExpress.WebUI.WebControl { /// - /// Eventargument, welches nach einer volstΓ€ndigen Validierung des Formulars mit allen Stuerelementen erstellt wird + /// Event argument, which is created after a complete validation of the form with all controls. /// public class ValidationResultEventArgs : EventArgs { /// - /// Bestimmt, ob die Validierung erfolgreich abgeschlossen wurde + /// Returns whether validation has completed successfully. /// public bool Valid { get; private set; } /// - /// Liefert oder setzt die Validierungsnachrichten + /// Returns the validation results. /// public List Results { get; private set; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// public ValidationResultEventArgs() { } /// - /// Constructor + /// Initializes a new instance of the class. /// - /// true wenn die Validierung erfolgreich abgeschlossen wurde, false sonst + /// true if validation is successful, false otherwise. public ValidationResultEventArgs(bool valid) { Valid = valid; diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index fadd2764..11f31d4d 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -47,7 +47,7 @@ - + @@ -176,10 +176,10 @@ + - @@ -204,7 +204,7 @@ - + @@ -361,7 +361,7 @@ Never - + diff --git a/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs b/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs index f2667d63..05ce7772 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs @@ -25,7 +25,7 @@ public class FragmentCacheItem public IFragmentContext Context { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The context of the fragment. /// The type. diff --git a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs b/src/WebExpress.WebUI/WebFragment/FragmentContext.cs index d637e8a1..ad0de631 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentContext.cs @@ -40,7 +40,7 @@ public class FragmentContext : IFragmentContext public bool Cache { get; internal set; } /// - /// Constructor + /// Initializes a new instance of the class. /// public FragmentContext() { diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs index 2f14c27b..5d46751c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs @@ -11,7 +11,7 @@ public class FragmentControlButtonLink : ControlButtonLink, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlButtonLink(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs index e6355395..bcdd87b6 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs @@ -11,7 +11,7 @@ public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragmen public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlDropdownItemLink(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs index 18b6c592..121c4b76 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs @@ -11,7 +11,7 @@ public class FragmentControlImage : ControlImage, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlImage(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs index 048527f8..2d668cb0 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs @@ -11,7 +11,7 @@ public class FragmentControlLink : ControlLink, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlLink(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs index 661e6430..df99e3cc 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs @@ -11,7 +11,7 @@ public class FragmentControlList : ControlList, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlList(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlFormularInline.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs similarity index 76% rename from src/WebExpress.WebUI/WebFragment/FragmentControlFormularInline.cs rename to src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs index 88bfd5ef..73e97aaa 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlFormularInline.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs @@ -3,18 +3,18 @@ namespace WebExpress.WebUI.WebFragment { - public class FragmentControlFormularInline : ControlFormInline, IFragment + public class FragmentControlModalForm : ControlModalForm, IFragment { /// - /// Liefert der Kontext + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. - public FragmentControlFormularInline(string id = null) + public FragmentControlModalForm(string id = null) : base(id) { } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlModalFormular.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlModalFormular.cs deleted file mode 100644 index 9258e8a4..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlModalFormular.cs +++ /dev/null @@ -1,32 +0,0 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlModalFormular : ControlModalFormular, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } - - /// - /// Constructor - /// - /// The id of the fragment or null. - public FragmentControlModalFormular(string id = null) - : base(id) - { - } - - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs index 9047245d..b46d5eb9 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs @@ -11,7 +11,7 @@ public class FragmentControlNavigationItemLink : ControlNavigationItemLink, IFra public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlNavigationItemLink(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs index fc8993bb..0cd39371 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs @@ -11,7 +11,7 @@ public class FragmentControlPanel : ControlPanel, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlPanel(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs index 9d93f6bf..29e0da5f 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs @@ -11,7 +11,7 @@ public class FragmentControlPanelFlexbox : ControlPanelFlexbox, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlPanelFlexbox(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs index d14d4413..03b7178c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs @@ -11,7 +11,7 @@ public class FragmentControlPanelTool : ControlPanelTool, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlPanelTool(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs index 8fe37e1d..818b16d1 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs @@ -11,7 +11,7 @@ public class FragmentControlSplitButtonItemLink : ControlSplitButtonItemLink, IF public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlSplitButtonItemLink(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs index 7a804849..1364ef7c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs @@ -11,7 +11,7 @@ public class FragmentControlText : ControlText, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlText(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs index a275f292..bc297cce 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs @@ -11,7 +11,7 @@ public class FragmentControlTree : ControlTree, IFragment public IFragmentContext FragmentContext { get; private set; } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The id of the fragment or null. public FragmentControlTree(string id = null) diff --git a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs index 265d505d..4a4d0934 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs @@ -41,7 +41,7 @@ public sealed class FragmentManager : IComponentPlugin private FragmentDictionary Dictionary { get; set; } = new FragmentDictionary(); /// - /// Constructor + /// Initializes a new instance of the class. /// internal FragmentManager() { @@ -185,7 +185,7 @@ public void Register(IPluginContext pluginContext) } // register fragment - foreach (var context in scopes.Any() ? scopes : new List(new[] { "" })) + foreach (var context in scopes.Count != 0 ? scopes : [""]) { var key = string.Join(":", section, context); diff --git a/src/WebExpress.WebUI/WebPage/PageControl.cs b/src/WebExpress.WebUI/WebPage/PageControl.cs index 178c78c0..16968653 100644 --- a/src/WebExpress.WebUI/WebPage/PageControl.cs +++ b/src/WebExpress.WebUI/WebPage/PageControl.cs @@ -27,7 +27,7 @@ namespace WebExpress.WebUI.WebPage protected List> Meta { get; } = new List>(); /// - /// Constructor + /// Initializes a new instance of the class. /// public PageControl() { @@ -53,7 +53,7 @@ public override void Initialization(IResourceContext context) CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.css")); CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.expand.css")); CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.form.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalformular.css")); + CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalform.css")); CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalpage.css")); CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.more.css")); CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.move.css")); @@ -70,7 +70,7 @@ public override void Initialization(IResourceContext context) HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalformular.js")); + HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); diff --git a/src/WebExpress.WebUI/WebPage/RenderContextControl.cs b/src/WebExpress.WebUI/WebPage/RenderContextControl.cs index c93ee87e..0e370c7e 100644 --- a/src/WebExpress.WebUI/WebPage/RenderContextControl.cs +++ b/src/WebExpress.WebUI/WebPage/RenderContextControl.cs @@ -15,7 +15,7 @@ public class RenderContextControl : RenderContext } /// - /// Constructor + /// Initializes a new instance of the class. /// public RenderContextControl() { @@ -23,7 +23,7 @@ public RenderContextControl() } /// - /// Constructor + /// Initializes a new instance of the class. /// /// The page where the control is rendered. /// The request. diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index ff0cf34a..3a958a22 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -19,7 +19,7 @@ public class VisualTreeControl : VisualTree public new List Content { get; } = new List(); /// - /// Constructor + /// Initializes a new instance of the class. /// public VisualTreeControl() { diff --git a/src/WebExpress.WebUI/WebResource/Asset.cs b/src/WebExpress.WebUI/WebResource/Asset.cs index 0966b0f0..312f1027 100644 --- a/src/WebExpress.WebUI/WebResource/Asset.cs +++ b/src/WebExpress.WebUI/WebResource/Asset.cs @@ -13,7 +13,7 @@ namespace WebExpress.WebUI.WebResource public sealed class Asset : ResourceAsset { /// - /// Constructor + /// Initializes a new instance of the class. /// public Asset() { diff --git a/src/WebExpress.WebUI/WebSection/SectionControl.cs b/src/WebExpress.WebUI/WebSection/SectionControl.cs new file mode 100644 index 00000000..d48a8edd --- /dev/null +++ b/src/WebExpress.WebUI/WebSection/SectionControl.cs @@ -0,0 +1,38 @@ +ο»Ώnamespace WebExpress.WebApp.WebSection +{ + /// + /// Definition of keys to identify sections in wen controls that can be occupied by components. + /// + public static class SectionControl + { + /// + /// Returns the header.preferences section. + /// + public const string HeaderPreferences = "header.preferences"; + + /// + /// Returns the header.primary section. + /// + public const string HeaderPrimary = "header.primary"; + + /// + /// Returns the header.secondary section. + /// + public const string HeaderSecondary = "header.secondary"; + + /// + /// Returns the footer.preferences section. + /// + public const string FooterPreferences = "footer.preferences"; + + /// + /// Returns the footer.primary section. + /// + public const string FooterPrimary = "footer.primary"; + + /// + /// Returns the footer.secondary section. + /// + public const string FooterSecondary = "footer.secondary"; + } +} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs index fa96b250..b566e673 100644 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs +++ b/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs @@ -41,7 +41,7 @@ public sealed class SettingPageManager : IComponentPlugin private SettingPageDictionary Dictionary { get; } = new SettingPageDictionary(); /// - /// Constructor + /// Initializes a new instance of the class. /// internal SettingPageManager() { From ba16d1a3d589f8ba9de959ae8a67dc221fdef879 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 27 Oct 2024 17:46:16 +0100 Subject: [PATCH 12/59] significant architectural changes and removal of modulemanager - removed: modulemanager from the architecture - updated: architecture for improved performance and maintainability - refactored: affected components to align with the new architecture --- src/WebExpress.WebUI/Module.cs | 46 --- src/WebExpress.WebUI/Plugin.cs | 45 --- .../WebAttribute/OptionAttribute.cs | 2 +- .../WebAttribute/SettingContextAttribute.cs | 5 +- .../WebAttribute/SettingGroupAttribute.cs | 5 +- .../WebAttribute/SettingHideAttribute.cs | 5 +- .../WebAttribute/SettingIconAttribute.cs | 9 +- .../WebAttribute/SettingSection.cs | 23 -- .../WebAttribute/SettingSectionAttribute.cs | 18 - src/WebExpress.WebUI/WebExpress.WebUI.csproj | 4 + .../WebFragment/FragmentContext.cs | 13 +- .../WebFragment/FragmentDictionary.cs | 14 - .../WebFragment/FragmentDictionaryItem.cs | 13 - .../WebFragment/FragmentItem.cs | 185 --------- .../WebFragment/FragmentItemComparer.cs | 1 + .../WebFragment/FragmentManager.cs | 367 +++++++++--------- .../WebFragment/IFragmentContext.cs | 13 +- .../WebFragment/IFragmentManager.cs | 57 +++ .../WebFragment/Model/FragmentDictionary.cs | 151 +++++++ .../WebFragment/Model/FragmentItem.cs | 75 ++++ src/WebExpress.WebUI/WebResource/Asset.cs | 22 -- .../WebSettingPage/IPageSetting.cs | 9 - .../WebSettingPage/SettingPageDictionary.cs | 112 ------ .../SettingPageDictionaryItem.cs | 48 --- .../SettingPageDictionaryItemContext.cs | 63 --- .../SettingPageDictionaryItemGroup.cs | 81 ---- .../SettingPageDictionaryItemSection.cs | 102 ----- .../WebSettingPage/SettingPageManager.cs | 275 ------------- .../WebSettingPage/SettingPageSearchResult.cs | 27 -- .../WebSettingPage/TimeSpanConverter.cs | 31 -- 30 files changed, 515 insertions(+), 1306 deletions(-) delete mode 100644 src/WebExpress.WebUI/Module.cs delete mode 100644 src/WebExpress.WebUI/Plugin.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingSection.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentDictionary.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentDictionaryItem.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentItem.cs create mode 100644 src/WebExpress.WebUI/WebFragment/IFragmentManager.cs create mode 100644 src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs create mode 100644 src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs delete mode 100644 src/WebExpress.WebUI/WebResource/Asset.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/IPageSetting.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageDictionary.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItem.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemContext.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemGroup.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemSection.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/SettingPageSearchResult.cs delete mode 100644 src/WebExpress.WebUI/WebSettingPage/TimeSpanConverter.cs diff --git a/src/WebExpress.WebUI/Module.cs b/src/WebExpress.WebUI/Module.cs deleted file mode 100644 index 7355f7f6..00000000 --- a/src/WebExpress.WebUI/Module.cs +++ /dev/null @@ -1,46 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebModule; - -namespace WebExpress.WebUI -{ - [Application("*")] - [Name("module.name")] - [Description("module.description")] - [Icon("/assets/img/Logo.png")] - [AssetPath("/")] - [ContextPath("/modules/wxui")] - public sealed class Module : WebCore.WebModule.Module - { - /// - /// Initializes a new instance of the class. - /// - public Module() - { - } - - /// - /// Instillation of the module. Here, for example, managed resources can be loaded. - /// - /// The context that applies to the execution of the plugin. - public override void Initialization(IModuleContext moduleContext) - { - base.Initialization(moduleContext); - } - - /// - /// Invoked when the module starts working. The call is concurrent. - /// - public override void Run() - { - base.Run(); - } - - /// - /// Release unmanaged resources that have been reserved during use. - /// - public override void Dispose() - { - base.Dispose(); - } - } -} diff --git a/src/WebExpress.WebUI/Plugin.cs b/src/WebExpress.WebUI/Plugin.cs deleted file mode 100644 index d6cec901..00000000 --- a/src/WebExpress.WebUI/Plugin.cs +++ /dev/null @@ -1,45 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebPlugin; - -[assembly: SystemPlugin()] - -namespace WebExpress.WebUI -{ - [Name("webexpress.webui")] - [Description("plugin.description")] - [Icon("/assets/img/Logo.png")] - public sealed class Plugin : WebCore.WebPlugin.Plugin - { - /// - /// Initializes a new instance of the class. - /// - public Plugin() - { - } - - /// - /// Initialization of the plugin. Here, for example, managed resources can be loaded. - /// - /// The context of the plugin that applies to the execution of the plugin. - public override void Initialization(IPluginContext context) - { - base.Initialization(context); - } - - /// - /// Called when the plugin starts working. Run is called concurrently. - /// - public override void Run() - { - base.Run(); - } - - /// - /// Release of unmanaged resources reserved during use. - /// - public override void Dispose() - { - base.Dispose(); - } - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs index 31f241ac..4f52b51b 100644 --- a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebAttribute /// Activation of options (e.g. WebEx.WebApp.Setting.SystemInformation for the display of system information). /// [AttributeUsage(AttributeTargets.Class)] - public class OptionAttribute : System.Attribute, IResourceAttribute + public class OptionAttribute : System.Attribute, IEndpointAttribute { /// /// Initializes a new instance of the class. diff --git a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs index 353af4e3..278a10b8 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs @@ -3,8 +3,11 @@ namespace WebExpress.WebUI.WebAttribute { + /// + /// Attribute to specify the context in which the settings page is associated. + /// [AttributeUsage(AttributeTargets.Class)] - public class SettingContextAttribute : Attribute, IResourceAttribute + public class SettingContextAttribute : Attribute, IEndpointAttribute { /// /// Initializes a new instance of the class. diff --git a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs index 531cc453..b7e3becd 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs @@ -3,8 +3,11 @@ namespace WebExpress.WebUI.WebAttribute { + /// + /// Attribute to define a setting group for identity. + /// [AttributeUsage(AttributeTargets.Class)] - public class SettingGroupAttribute : System.Attribute, IResourceAttribute + public class SettingGroupAttribute : System.Attribute, IEndpointAttribute { /// /// Initializes a new instance of the class. diff --git a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs index 6a9ecc30..c74e28ea 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs @@ -2,7 +2,10 @@ namespace WebExpress.WebUI.WebAttribute { - public class SettingHideAttribute : System.Attribute, IResourceAttribute + /// + /// Represents an attribute that hides a setting in the web UI. + /// + public class SettingHideAttribute : System.Attribute, IEndpointAttribute { /// /// Initializes a new instance of the class. diff --git a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs index 35f7bf95..ebc874fe 100644 --- a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs +++ b/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs @@ -1,9 +1,12 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebAttribute; +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebAttribute { - public class SettingIconAttribute : System.Attribute, IResourceAttribute + /// + /// Attribute to set an icon for a setting. + /// + public class SettingIconAttribute : System.Attribute, IEndpointAttribute { /// /// Initializes a new instance of the class. diff --git a/src/WebExpress.WebUI/WebAttribute/SettingSection.cs b/src/WebExpress.WebUI/WebAttribute/SettingSection.cs deleted file mode 100644 index feb60892..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingSection.cs +++ /dev/null @@ -1,23 +0,0 @@ -ο»Ώnamespace WebExpress.WebUI.WebAttribute -{ - /// - /// Definition of keys for the identification of sections in Wen pages, which can be occupied by components. - /// - public enum SettingSection - { - /// - /// Returns the preference section. - /// - Preferences, - - /// - /// Returns the primary section. - /// - Primary, - - /// - /// Returns the secondary section. - /// - Secondary - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs deleted file mode 100644 index f676c888..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingSectionAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebAttribute; - -namespace WebExpress.WebUI.WebAttribute -{ - [AttributeUsage(AttributeTargets.Class)] - public class SettingSectionAttribute : System.Attribute, IResourceAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The section where the settings page is listed. - public SettingSectionAttribute(SettingSection section) - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index 11f31d4d..a3e3d34a 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -394,4 +394,8 @@ + + + + diff --git a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs b/src/WebExpress.WebUI/WebFragment/FragmentContext.cs index ad0de631..566ed0b8 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentContext.cs @@ -2,11 +2,14 @@ using System.Globalization; using WebExpress.WebCore.WebApplication; using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPlugin; namespace WebExpress.WebUI.WebFragment { + /// + /// Represents the context for a web fragment, including plugin context, application context, + /// conditions for activation, culture information, and caching behavior. + /// public class FragmentContext : IFragmentContext { /// @@ -17,17 +20,17 @@ public class FragmentContext : IFragmentContext /// /// Returns the application context. /// - public IApplicationContext ApplicationContext => ModuleContext.ApplicationContext; + public IApplicationContext ApplicationContext { get; internal set; } /// - /// Returns the module context. + /// Gets the unique identifier for the fragment. /// - public IModuleContext ModuleContext { get; internal set; } + public string FragmentId { get; internal set; } /// /// Returns the conditions that must be met for the component to be active. /// - public ICollection Conditions { get; internal set; } = new List(); + public ICollection Conditions { get; internal set; } = []; /// /// Returns the culture. diff --git a/src/WebExpress.WebUI/WebFragment/FragmentDictionary.cs b/src/WebExpress.WebUI/WebFragment/FragmentDictionary.cs deleted file mode 100644 index ccb262bf..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentDictionary.cs +++ /dev/null @@ -1,14 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// component directory - /// key = plugin context - /// value { key = section:context, value = component item } - /// - internal class FragmentDictionary : Dictionary - { - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentDictionaryItem.cs b/src/WebExpress.WebUI/WebFragment/FragmentDictionaryItem.cs deleted file mode 100644 index d28f2827..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentDictionaryItem.cs +++ /dev/null @@ -1,13 +0,0 @@ -ο»Ώusing System.Collections.Generic; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// component directory item - /// key = section:context - /// value = component items - /// - internal class FragmentDictionaryItem : Dictionary> - { - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentItem.cs b/src/WebExpress.WebUI/WebFragment/FragmentItem.cs deleted file mode 100644 index 8c6663c2..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentItem.cs +++ /dev/null @@ -1,185 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebLog; -using WebExpress.WebCore.WebModule; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Fragments are components that can be integrated into pages to dynamically expand functionalities. - /// - internal class FragmentItem : IDisposable - { - /// - /// An event that fires when an fragment is added. - /// - public event EventHandler AddFragment; - - /// - /// An event that fires when an fragment is removed. - /// - public event EventHandler RemoveFragment; - - /// - /// Returns the context of the associated plugin. - /// - public IPluginContext PluginContext { get; set; } - - /// - /// Returns the module id. - /// - public string ModuleId { get; set; } - - /// - /// The type of fragment. - /// - public Type FragmentClass { get; set; } - - /// - /// Returns the section. - /// - public string Section { get; set; } - - /// - /// Returns the scopes. - /// - public IEnumerable Scopes { get; set; } - - /// - /// Returns the conditions that must be met for the component to be active. - /// - public ICollection Conditions { get; set; } - - /// - /// The order of the fragment. - /// - public int Order { get; set; } - - /// - /// Determines whether the component is created once and reused on each execution. - /// - public bool Cache { get; set; } - - /// - /// Returns the log to write status messages to the console and to a log file. - /// - public Log Log { get; internal set; } - - /// - /// Returns the directory where the module instances are listed. - /// - private IDictionary Dictionary { get; } - = new Dictionary(); - - /// - /// Returns all fragment contexts. - /// - public IEnumerable FragmentContexts => Dictionary.Values - .Select(x => x); - - /// - /// Adds an module assignment - /// - /// The context of the module. - public void AddModule(IModuleContext moduleContext) - { - // only if no instance has been created yet - if (Dictionary.ContainsKey(moduleContext)) - { - Log.Warning(message: InternationalizationManager.I18N("webexpress:fragmentmanager.addfragment.duplicate", FragmentClass.Name, moduleContext.ModuleId)); - - return; - } - - // create context - var fragmentContext = new FragmentContext() - { - PluginContext = PluginContext, - ModuleContext = moduleContext, - Conditions = Conditions, - Cache = Cache - }; - - Dictionary.Add(moduleContext, fragmentContext); - - OnAddFragment(fragmentContext); - } - - /// - /// Remove an module assignment - /// - /// The context of the module. - public void DetachModule(IModuleContext moduleContext) - { - // not an assignment has been created yet - if (!Dictionary.ContainsKey(moduleContext)) - { - return; - } - - foreach (var fragmentContext in Dictionary.Values) - { - OnRemoveFragment(fragmentContext); - } - - Dictionary.Remove(moduleContext); - } - - /// - /// Checks whether a module context is already assigned to the item. - /// - /// The module context. - /// True a mapping exists, false otherwise. - public bool IsAssociatedWithModule(IModuleContext moduleContext) - { - return Dictionary.ContainsKey(moduleContext); - } - - /// - /// Raises the AddFragment event. - /// - /// The fragment context. - private void OnAddFragment(IFragmentContext fragmentContext) - { - AddFragment?.Invoke(this, fragmentContext); - } - - /// - /// Raises the RemoveFragment event. - /// - /// The fragment context. - private void OnRemoveFragment(IFragmentContext fragmentContext) - { - RemoveFragment?.Invoke(this, fragmentContext); - } - - /// - /// Performs application-specific tasks related to sharing, returning, or resetting unmanaged resources. - /// - public void Dispose() - { - foreach (Delegate d in AddFragment.GetInvocationList()) - { - AddFragment -= (EventHandler)d; - } - - foreach (Delegate d in RemoveFragment.GetInvocationList()) - { - RemoveFragment -= (EventHandler)d; - } - } - - /// - /// Convert the resource element to a string. - /// - /// The resource element in its string representation. - public override string ToString() - { - return $"Fragment '{FragmentClass.Name}'"; - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs b/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs index 110865bb..1d7d2180 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs @@ -1,4 +1,5 @@ ο»Ώusing System.Collections.Generic; +using WebExpress.WebUI.WebFragment.Model; namespace WebExpress.WebUI.WebFragment { diff --git a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs index 4a4d0934..055b4c69 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs @@ -7,19 +7,23 @@ using WebExpress.WebCore.WebAttribute; using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPage; using WebExpress.WebCore.WebPlugin; using WebExpress.WebUI.WebAttribute; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment.Model; namespace WebExpress.WebUI.WebFragment { /// /// Fragment manager. /// - public sealed class FragmentManager : IComponentPlugin + public sealed class FragmentManager : IFragmentManager { + private readonly IComponentHub _componentHub; + private readonly IHttpServerContext _httpServerContext; + private readonly FragmentDictionary _dictionary = []; + /// /// An event that fires when an fragment is added. /// @@ -30,72 +34,68 @@ public sealed class FragmentManager : IComponentPlugin /// public event EventHandler RemoveFragment; - /// - /// Returns the reference to the context of the host. - /// - public IHttpServerContext HttpServerContext { get; private set; } - - /// - /// Returns or sets the directory where the components are listed. - /// - private FragmentDictionary Dictionary { get; set; } = new FragmentDictionary(); - /// /// Initializes a new instance of the class. /// - internal FragmentManager() + /// The component hub. + /// The reference to the context of the host. + private FragmentManager(IComponentHub componentHub, IHttpServerContext httpServerContext) { - ComponentManager.PluginManager.AddPlugin += (s, pluginContext) => - { - Register(pluginContext); - }; - - ComponentManager.PluginManager.RemovePlugin += (s, pluginContext) => - { - Remove(pluginContext); - }; + _componentHub = componentHub; + _httpServerContext = httpServerContext; - ComponentManager.ModuleManager.AddModule += (sender, moduleContext) => - { - AssignToModule(moduleContext); - }; + _componentHub.PluginManager.AddPlugin += OnAddPlugin; + _componentHub.PluginManager.RemovePlugin += OnRemovePlugin; + _componentHub.ApplicationManager.AddApplication += OnAddApplication; + _componentHub.ApplicationManager.RemoveApplication += OnRemoveApplication; - ComponentManager.ModuleManager.RemoveModule += (sender, moduleContext) => - { - DetachFromModule(moduleContext); - }; + _httpServerContext.Log.Debug + ( + I18N.Translate("webexpress.webui:fragmentmanager.initialization") + ); } /// - /// Initialization + /// Discovers and binds fragments to an application. /// - /// The reference to the context of the host. - public void Initialization(IHttpServerContext context) + /// The context of the plugin whose fragments are to be associated. + private void Register(IPluginContext pluginContext) { - HttpServerContext = context; + if (_dictionary.ContainsKey(pluginContext)) + { + return; + } - HttpServerContext.Log.Debug - ( - InternationalizationManager.I18N("webexpress.webui:fragmentmanager.initialization") - ); + Register(pluginContext, _componentHub.ApplicationManager.GetApplications(pluginContext)); } /// - /// Discovers and registers entries from the specified plugin. + /// Discovers and binds fragments to an application. /// - /// A context of a plugin whose elements are to be registered. - public void Register(IPluginContext pluginContext) + /// The context of the application whose fragments are to be associated. + private void Register(IApplicationContext applicationContext) { - // register plugin - if (!Dictionary.ContainsKey(pluginContext)) + foreach (var pluginContext in _componentHub.PluginManager.GetPlugins(applicationContext)) { - Dictionary.Add(pluginContext, new FragmentDictionaryItem()); + if (_dictionary.TryGetValue(pluginContext, out var appDict) && appDict.ContainsKey(applicationContext)) + { + continue; + } + + Register(pluginContext, [applicationContext]); } + } - var pluginDictionary = Dictionary[pluginContext]; + /// + /// Registers pages for a given plugin and application context. + /// + /// The plugin context. + /// The application context (optional). + private void Register(IPluginContext pluginContext, IEnumerable applicationContexts) + { var assembly = pluginContext.Assembly; - foreach (var fragment in assembly.GetTypes().Where + foreach (var fragmentType in assembly.GetTypes().Where ( x => x.IsClass && x.IsSealed && @@ -106,7 +106,7 @@ public void Register(IPluginContext pluginContext) ) )) { - var moduleId = string.Empty; + var id = fragmentType.FullName?.ToLower(); var scopes = new List(); var section = string.Empty; var conditions = new List(); @@ -114,17 +114,13 @@ public void Register(IPluginContext pluginContext) var order = 0; // determining attributes - foreach (var customAttribute in fragment.CustomAttributes.Where + foreach (var customAttribute in fragmentType.CustomAttributes.Where ( x => x.AttributeType.GetInterfaces() - .Contains(typeof(IResourceAttribute)) + .Contains(typeof(IEndpointAttribute)) )) { - if (customAttribute.AttributeType.Name == typeof(ModuleAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ModuleAttribute<>).Namespace) - { - moduleId = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower(); - } - else if (customAttribute.AttributeType.Name == typeof(ScopeAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ScopeAttribute<>).Namespace) + if (customAttribute.AttributeType.Name == typeof(ScopeAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ScopeAttribute<>).Namespace) { scopes.Add(customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower()); } @@ -139,7 +135,7 @@ public void Register(IPluginContext pluginContext) } } - foreach (var customAttribute in fragment.CustomAttributes.Where + foreach (var customAttribute in fragmentType.CustomAttributes.Where ( x => x.AttributeType.GetInterfaces().Contains(typeof(IFragmentAttribute)) )) @@ -160,23 +156,10 @@ public void Register(IPluginContext pluginContext) } } - // check module - if (string.IsNullOrWhiteSpace(moduleId)) - { - HttpServerContext.Log.Warning(InternationalizationManager.I18N - ( - "webexpress.webui:fragmentmanager.moduleless", - fragment.Name, - pluginContext.PluginId - )); - - continue; - } - // check section if (string.IsNullOrWhiteSpace(section)) { - HttpServerContext.Log.Warning(InternationalizationManager.I18N + _httpServerContext.Log.Warning(I18N.Translate ( "webexpress.webui:fragmentmanager.error.section" )); @@ -184,108 +167,92 @@ public void Register(IPluginContext pluginContext) continue; } - // register fragment - foreach (var context in scopes.Count != 0 ? scopes : [""]) + // assign the fragment to existing applications + foreach (var applicationContext in _componentHub.ApplicationManager.GetApplications(pluginContext)) { - var key = string.Join(":", section, context); - - if (!pluginDictionary.ContainsKey(key)) + // register fragment + foreach (var context in scopes.Count != 0 ? scopes : [""]) { - pluginDictionary.Add(key, new List()); + var fragmentContext = new FragmentContext() + { + PluginContext = pluginContext, + ApplicationContext = applicationContext, + FragmentId = id, + Cache = cache, + //Scopes = scopes, + Conditions = conditions + }; + + var fragmentItem = new FragmentItem() + { + PluginContext = pluginContext, + ApplicationContext = applicationContext, + FragmentContext = fragmentContext, + FragmentClass = fragmentType, + Order = order, + Cache = cache, + Conditions = conditions, + Section = section, + Scopes = scopes + }; + + if (_dictionary.AddFragmentItem(pluginContext, applicationContext, fragmentItem)) + { + OnAddFragment(fragmentContext); + + _httpServerContext?.Log.Debug + ( + I18N.Translate + ( + "webexpress:fragmentmanager.register", + id, + section, + applicationContext.ApplicationId + ) + ); + } } - - var dictItem = pluginDictionary[key]; - - var fragmentItem = new FragmentItem() - { - PluginContext = pluginContext, - ModuleId = moduleId, - FragmentClass = fragment, - Order = order, - Cache = cache, - Conditions = conditions, - Section = section, - Scopes = scopes - }; - - dictItem.Add(fragmentItem); - - fragmentItem.AddFragment += (s, e) => - { - OnAddFragment(e); - }; - - fragmentItem.RemoveFragment += (s, e) => - { - OnRemoveFragment(e); - }; - - HttpServerContext.Log.Debug(InternationalizationManager.I18N - ( - "webexpress.webui:fragmentmanager.register", - fragment.Name, - section, - moduleId - )); - } - - // assign the fragments to existing modules. - foreach (var moduleContext in ComponentManager.ModuleManager.GetModules(pluginContext, moduleId)) - { - AssignToModule(moduleContext); } } - } - /// - /// Discovers and registers entries from the specified plugin. - /// - /// A list with plugin contexts that contain the components. - public void Register(IEnumerable pluginContexts) - { - foreach (var pluginContext in pluginContexts) - { - Register(pluginContext); - } + Log(); } /// /// Removes all components associated with the specified plugin context. /// /// The context of the plugin that contains the components to remove. - public void Remove(IPluginContext pluginContext) + internal void Remove(IPluginContext pluginContext) { - Dictionary.Remove(pluginContext); - } + if (pluginContext == null) + { + return; + } - /// - /// Assign existing resources to the module. - /// - /// The context of the module. - private void AssignToModule(IModuleContext moduleContext) - { - foreach (var resourceItem in Dictionary.Values - .SelectMany(x => x.Values) - .SelectMany(x => x) - .Where(x => x.ModuleId.Equals(moduleContext?.ModuleId, StringComparison.OrdinalIgnoreCase)) - .Where(x => !x.IsAssociatedWithModule(moduleContext))) + var fragments = _dictionary.RemoveFragments(pluginContext); + + foreach (var fragment in fragments) { - resourceItem.AddModule(moduleContext); + OnRemoveFragment(fragment); } } /// - /// Remove an existing modules to the application. + /// Removes all fragments associated with the specified application context. /// - /// The context of the module. - private void DetachFromModule(IModuleContext moduleContext) + /// The context of the application that contains the fragments to remove. + internal void Remove(IApplicationContext applicationContext) { - foreach (var resourceItem in Dictionary.Values - .SelectMany(x => x.Values) - .SelectMany(x => x) - .Where(x => !x.IsAssociatedWithModule(moduleContext))) + if (applicationContext == null) + { + return; + } + + var fragments = _dictionary.RemoveFragments(applicationContext); + + foreach (var fragment in fragments) { - resourceItem.DetachModule(moduleContext); + OnRemoveFragment(fragment); } } @@ -307,6 +274,46 @@ private void OnRemoveFragment(IFragmentContext fragmentContext) RemoveFragment?.Invoke(this, fragmentContext); } + /// + /// Raises the event when an plugin is added. + /// + /// The source of the event. + /// The context of the plugin being added. + private void OnAddPlugin(object sender, IPluginContext e) + { + Register(e); + } + + /// + /// Raises the event when a plugin is removed. + /// + /// The source of the event. + /// The context of the plugin being removed. + private void OnRemovePlugin(object sender, IPluginContext e) + { + Remove(e); + } + + /// + /// Raises the event when an application is added. + /// + /// The source of the event. + /// The context of the application being added. + private void OnAddApplication(object sender, IApplicationContext e) + { + Register(e); + } + + /// + /// Raises the event when an application is removed. + /// + /// The source of the event. + /// The context of the application being removed. + private void OnRemoveApplication(object sender, IApplicationContext e) + { + Remove(e); + } + /// /// Returns all fragment contexts that belong to a given section. /// @@ -338,7 +345,7 @@ public IEnumerable GetFragmentContexts(string section, IApplic /// An enumeration of the filtered fragment contexts. private IEnumerable GetFragmentItems(string section) { - return Dictionary.Values + return _dictionary.Values .Where(x => x.ContainsKey(section?.ToLower())) .SelectMany(x => x[section?.ToLower()]) .Select(x => x); @@ -373,7 +380,7 @@ public IEnumerable GetCacheableFragments IEnumerable scopes ) where T : IControl { - var applicationContext = page?.ResourceContext.ApplicationContext; + var applicationContext = page?.ResourceContext?.ModuleContext?.ApplicationContext; scopes ??= Enumerable.Empty(); var fragmentItems = GetFragmentItems($"{section}:") @@ -407,41 +414,51 @@ IEnumerable scopes /// A list with the fragment items. private IEnumerable GetFragmentItems(IPluginContext pluginContext) { - if (!Dictionary.ContainsKey(pluginContext)) + if (!_dictionary.ContainsKey(pluginContext)) { - return Enumerable.Empty(); + return []; } - return Dictionary[pluginContext].Values + return _dictionary[pluginContext].Values .SelectMany(x => x); } /// /// Information about the component is collected and prepared for output in the log. /// - /// The context of the plugin. - /// A list of log entries. - /// The shaft deep. - public void PrepareForLog(IPluginContext pluginContext, IList output, int deep) + private void Log() { - output.Add - ( - string.Empty.PadRight(deep) + - InternationalizationManager.I18N("webexpress.webui:fragmentmanager.titel") - ); + //output.Add + //( + // string.Empty.PadRight(deep) + + // I18N.Translate("webexpress.webui:fragmentmanager.titel") + //); + + //foreach (var fragmentItem in GetFragmentItems(pluginContext)) + //{ + // output.Add + // ( + // string.Empty.PadRight(deep + 2) + + // I18N.Translate + // ( + // "webexpress.webui:fragmentmanager.fragment", + // fragmentItem.FragmentClass.Name + // ) + // ); + //} + } - foreach (var fragmentItem in GetFragmentItems(pluginContext)) - { - output.Add - ( - string.Empty.PadRight(deep + 2) + - InternationalizationManager.I18N - ( - "webexpress.webui:fragmentmanager.fragment", - fragmentItem.FragmentClass.Name - ) - ); - } + /// + /// Release of unmanaged resources reserved during use. + /// + public void Dispose() + { + _componentHub.PluginManager.AddPlugin -= OnAddPlugin; + _componentHub.PluginManager.RemovePlugin -= OnRemovePlugin; + _componentHub.ApplicationManager.AddApplication -= OnAddApplication; + _componentHub.ApplicationManager.RemoveApplication -= OnRemoveApplication; + + GC.SuppressFinalize(this); } } } diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs b/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs index c556a64c..24b919dc 100644 --- a/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs +++ b/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs @@ -1,13 +1,16 @@ ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPlugin; namespace WebExpress.WebUI.WebFragment { - public interface IFragmentContext : II18N + /// + /// Interface representing the context of a web fragment. + /// Provides access to plugin context, application context, conditions for activation, and caching behavior. + /// + public interface IFragmentContext : IContext { /// /// Returns the context of the associated plugin. @@ -20,9 +23,9 @@ public interface IFragmentContext : II18N IApplicationContext ApplicationContext { get; } /// - /// Returns the module context. + /// Gets the unique identifier for the fragment. /// - IModuleContext ModuleContext { get; } + string FragmentId { get; } /// /// Returns the conditions that must be met for the component to be active. diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs b/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs new file mode 100644 index 00000000..49bb76fc --- /dev/null +++ b/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs @@ -0,0 +1,57 @@ +ο»Ώusing System; +using System.Collections.Generic; +using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebComponent; +using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Interface for managing web fragments. + /// + public interface IFragmentManager : IComponentManager + { + /// + /// An event that fires when a fragment is added. + /// + public event EventHandler AddFragment; + + /// + /// An event that fires when a fragment is removed. + /// + public event EventHandler RemoveFragment; + + /// + /// Returns all fragment contexts that belong to a given section. + /// + /// The section where the fragment is embedded. + /// An enumeration of the filtered fragment contexts. + IEnumerable GetFragmentContexts(string section); + + /// + /// Returns all fragment contexts that belong to a given application. + /// + /// The section where the fragment is embedded. + /// The allpication context. + /// An enumeration of the filtered fragment contexts. + IEnumerable GetFragmentContexts(string section, IApplicationContext applicationContext); + + /// + /// Determines all fragments that match the parameters. + /// + /// The section where the fragment is embedded. + /// The page that holds the fragments. + /// A list of fragments. + IEnumerable GetCacheableFragments(string section, IPage page) where T : IControl; + + /// + /// Determines all fragments that match the parameters. + /// + /// The section where the fragment is embedded. + /// The page that holds the fragments. + /// The scopes where the fragments exists. + /// A list of fragments. + IEnumerable GetCacheableFragments(string section, IPage page, IEnumerable scopes) where T : IControl; + } +} diff --git a/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs b/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs new file mode 100644 index 00000000..90b9ac4f --- /dev/null +++ b/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs @@ -0,0 +1,151 @@ +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebPlugin; + +namespace WebExpress.WebUI.WebFragment.Model +{ + /// + /// Represents a dictionary that maps plugin contexts to application contexts, + /// which in turn maps to a dictionary of string keys and lists of FragmentItem objects. + /// key = plugin context + /// value application context { key = section:context, value = component item } + /// + internal class FragmentDictionary : Dictionary>>> + { + /// + /// Adds a fragment item to the dictionary. + /// + /// The plugin context. + /// The application context. + /// The fragment item. + /// True if the fragment item was added successfully, false if an element with the same status code already exists. + public bool AddFragmentItem(IPluginContext pluginContext, IApplicationContext applicationContext, FragmentItem fragmentItem) + { + var type = fragmentItem.FragmentClass; + + if (!typeof(IFragment).IsAssignableFrom(type)) + { + return false; + } + + if (!ContainsKey(pluginContext)) + { + this[pluginContext] = []; + } + + var appContextDict = this[pluginContext]; + + if (!appContextDict.ContainsKey(applicationContext)) + { + appContextDict[applicationContext] = []; + } + + var fragmentDict = appContextDict[applicationContext]; + + if (!fragmentDict.ContainsKey(type)) + { + fragmentDict[type] = []; + return true; + } + + return false; // item with the same fragment class already exists + } + + /// + /// Removes fragments from the dictionary. + /// + /// The plugin context. + /// An IEnumerable of fragment contexts that were removed. + public IEnumerable RemoveFragments(IPluginContext pluginContext) + { + var fragments = GetFragments(pluginContext); + + Remove(pluginContext); + + return fragments; + } + + /// + /// Removes fragments from the dictionary. + /// + /// The application context. + /// An IEnumerable of fragment contexts that were removed. + public IEnumerable RemoveFragments(IApplicationContext applicationContext) + { + foreach (var appContextDict in this) + { + if (appContextDict.Value.TryGetValue(applicationContext, out var fragmentDict)) + { + appContextDict.Value.Remove(applicationContext); + + if (appContextDict.Value.Count == 0) + { + Remove(appContextDict.Key); + } + + return fragmentDict.Values.SelectMany(x => x).Select(x => x.FragmentContext); + } + } + + return []; + } + + /// + /// Returns the fragment items from the dictionary. + /// + /// The type of fragment. + /// The application context. + /// An IEnumerable of fragment items + public IEnumerable GetFragmentItems(IApplicationContext applicationContext) where T : IFragment + { + return GetFragmentItems(applicationContext, typeof(T)); + } + + /// + /// Returns the fragment items from the dictionary. + /// + /// The application context. + /// The type of fragment. + /// An IEnumerable of fragment items + public IEnumerable GetFragmentItems(IApplicationContext applicationContext, Type fragmentType) + { + if (!typeof(IFragment).IsAssignableFrom(fragmentType)) + { + return []; + } + + if (ContainsKey(applicationContext?.PluginContext)) + { + var appContextDict = this[applicationContext?.PluginContext]; + + if (appContextDict.ContainsKey(applicationContext)) + { + var fragmentDict = appContextDict[applicationContext]; + + if (fragmentDict.ContainsKey(fragmentType)) + { + return fragmentDict[fragmentType]; + } + } + } + + return []; + } + + /// + /// Returns all fragment contexts for a given plugin context. + /// + /// The plugin context. + /// An IEnumerable of fragment contexts. + public IEnumerable GetFragments(IPluginContext pluginContext) + { + return this.Where(x => x.Key == pluginContext) + .SelectMany(x => x.Value.Values) + .SelectMany(x => x.Values) + .SelectMany(x => x) + .Select(x => x.FragmentContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs b/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs new file mode 100644 index 00000000..93431501 --- /dev/null +++ b/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs @@ -0,0 +1,75 @@ +ο»Ώusing System; +using System.Collections.Generic; +using WebExpress.WebCore.WebApplication; +using WebExpress.WebCore.WebCondition; +using WebExpress.WebCore.WebPlugin; + +namespace WebExpress.WebUI.WebFragment.Model +{ + /// + /// Fragments are components that can be integrated into pages to dynamically expand functionalities. + /// + internal class FragmentItem : IDisposable + { + /// + /// Returns the context of the associated plugin. + /// + public IPluginContext PluginContext { get; set; } + + /// + /// Returns the application context. + /// + public IApplicationContext ApplicationContext { get; set; } + + /// + /// Returns the fragment context. + /// + public IFragmentContext FragmentContext { get; set; } + + /// + /// The type of fragment. + /// + public Type FragmentClass { get; set; } + + /// + /// Returns the section. + /// + public string Section { get; set; } + + /// + /// Returns the scopes. + /// + public IEnumerable Scopes { get; set; } + + /// + /// Returns the conditions that must be met for the component to be active. + /// + public ICollection Conditions { get; set; } + + /// + /// The order of the fragment. + /// + public int Order { get; set; } + + /// + /// Determines whether the component is created once and reused on each execution. + /// + public bool Cache { get; set; } + + /// + /// Performs application-specific tasks related to sharing, returning, or resetting unmanaged resources. + /// + public void Dispose() + { + } + + /// + /// Convert the resource element to a string. + /// + /// The resource element in its string representation. + public override string ToString() + { + return $"Fragment: '{FragmentContext.FragmentId}'"; + } + } +} diff --git a/src/WebExpress.WebUI/WebResource/Asset.cs b/src/WebExpress.WebUI/WebResource/Asset.cs deleted file mode 100644 index 312f1027..00000000 --- a/src/WebExpress.WebUI/WebResource/Asset.cs +++ /dev/null @@ -1,22 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebResource; - -namespace WebExpress.WebUI.WebResource -{ - /// - /// Delivery of a resource embedded in the assembly. - /// - [Segment("assets")] - [ContextPath("/")] - [IncludeSubPaths(true)] - [Module] - public sealed class Asset : ResourceAsset - { - /// - /// Initializes a new instance of the class. - /// - public Asset() - { - } - } -} \ No newline at end of file diff --git a/src/WebExpress.WebUI/WebSettingPage/IPageSetting.cs b/src/WebExpress.WebUI/WebSettingPage/IPageSetting.cs deleted file mode 100644 index 0a612886..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/IPageSetting.cs +++ /dev/null @@ -1,9 +0,0 @@ -ο»Ώnamespace WebExpress.WebUI.WebSettingPage -{ - /// - /// Marks a class as a settings page. - /// - public interface IPageSetting - { - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionary.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionary.cs deleted file mode 100644 index ae2b5d4e..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionary.cs +++ /dev/null @@ -1,112 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebModule; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.SettingPage -{ - /// - /// key = The context of the plugin. - /// value = meta data - /// - public class SettingPageDictionary : Dictionary - { - /// - /// Adds a settings page. - /// - /// The context of the plugin. - /// The settings page to insert. - public void AddPage(IPluginContext pluginContext, SettingPageDictionaryItem item) - { - if (!ContainsKey(pluginContext)) - { - Add(pluginContext, new SettingPageDictionaryItemContext()); - } - - this[pluginContext].AddPage(item.Context, item.Section, item.Group, item); - } - - /// - /// Finds a settings page in an application by its id. - /// - /// The context of the application. - /// The context of the module. - /// The id of the setting page. - /// The setting page found or null. - /// - public SettingPageSearchResult FindPage(IApplicationContext application, IModuleContext module, string pageId) - { - var results = Values - .SelectMany(c => c.Values) - .SelectMany(s => s.Values) - .SelectMany(g => g.Values) - .SelectMany(i => i) - .Where(x => x != null && x.ModuleId.Equals(module.ModuleId, StringComparison.OrdinalIgnoreCase)) - .Select(x => new SettingPageSearchResult() - { - Context = x.Context, - Section = x.Section, - Group = x.Group, - Item = x - }); - - return results.FirstOrDefault(); - } - - /// - /// Returns all existing contexts. - /// - /// The application id. - /// A collection of all contexts. - /// - public IEnumerable GetContexts(string applicationId) - { - var resourceManager = ComponentManager.ResourceManager; - - var results = Values - .Where( - x => x.SelectMany(c => c.Value) - .SelectMany(s => s.Value) - .SelectMany(g => g.Value) - .Where - ( - x => - resourceManager.GetResorces(applicationId, x.ModuleId, x.ResourceId) != null - ) - .Any() - ); - - return results; - } - - /// - /// Returns all sections that have the same setting context. - /// - /// The application id. - /// The context. - /// A listing of all sections of the same context. - /// - public IEnumerable GetSections(string applicationId, string context) - { - var resourceManager = ComponentManager.ResourceManager; - - var results = Values - .SelectMany(x => x.Values) - .Where( - x => x.SelectMany(s => s.Value) - .SelectMany(g => g.Value) - .Where - ( - x => x != null && - resourceManager.GetResorces(applicationId, x.ModuleId, x.ResourceId) != null - ) - .Any() - ); - - return results; - } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItem.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItem.cs deleted file mode 100644 index 19e7106a..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItem.cs +++ /dev/null @@ -1,48 +0,0 @@ -ο»Ώusing WebExpress.WebUI.WebAttribute; -using WebExpress.WebUI.WebControl; - -namespace WebExpress.WebUI.SettingPage -{ - public class SettingPageDictionaryItem - { - /// - /// Returns the id of the setting page. - /// - public string Id { get; internal set; } - - /// - /// Returns the mudule context. - /// - public string ModuleId { get; internal set; } - - /// - /// Returns the resource. - /// - public string ResourceId { get; internal set; } - - /// - /// Determines whether the page should be displayed or hidden. - /// - public bool Hide { get; internal set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; internal set; } - - /// - /// Returns the setting context. - /// - public string Context { get; internal set; } - - /// - /// Returns the section. - /// - public SettingSection Section { get; internal set; } - - /// - /// Returns the group. - /// - public string Group { get; internal set; } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemContext.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemContext.cs deleted file mode 100644 index 1ff1b7b6..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemContext.cs +++ /dev/null @@ -1,63 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebUI.WebAttribute; - -namespace WebExpress.WebUI.SettingPage -{ - public class SettingPageDictionaryItemContext : Dictionary - { - /// - /// Adds a page. - /// - /// The settig context. - /// The section. - /// The group. - /// The item to insert. - public void AddPage(string context, SettingSection section, string group, SettingPageDictionaryItem page) - { - context ??= "*"; - - // register context - if (!ContainsKey(context)) - { - Add(context, new SettingPageDictionaryItemSection()); - } - - this[context].AddPage(section, group, page); - } - - /// - /// Searches for a setting page by its id. - /// - /// The setting site. - /// The setting page found or null. - public SettingPageSearchResult FindPage(string pageId) - { - foreach (var v in this) - { - var path = v.Value.FindPage(pageId); - if (path != null) - { - path.Context = v.Key; - return path; - } - } - - return null; - } - - /// - /// Provide all sections that have the same setting context. - /// - /// The setting context. - /// A listing of all sections of the same context. - public SettingPageDictionaryItemSection GetSections(string context) - { - if (ContainsKey(context)) - { - return this[context]; - } - - return null; - } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemGroup.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemGroup.cs deleted file mode 100644 index 1a81ed34..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemGroup.cs +++ /dev/null @@ -1,81 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; - -namespace WebExpress.WebUI.SettingPage -{ - public class SettingPageDictionaryItemGroup : Dictionary> - { - /// - /// Adds a page. - /// - /// The group. - /// The item to insert. - public void AddPage(string group, SettingPageDictionaryItem page) - { - group ??= string.Empty; - - // register group. - if (!ContainsKey(group)) - { - Add(group, new List()); - } - - this[group].Add(page); - } - - /// - /// Searches for an item based on its Id. - /// - /// The setting site. - /// The setting page found or null. - public SettingPageSearchResult FindPage(string pageId) - { - foreach (var v in this) - { - var item = v.Value.Where(x => x.Id == pageId).FirstOrDefault(); - if (item != null) - { - return new SettingPageSearchResult() { Group = v.Key, Item = item }; - } - } - - return null; - } - - /// - /// Returns the first setting page. - /// - /// The first setting page. - public SettingPageSearchResult FindFirstPage() - { - var firstItem = default(SettingPageDictionaryItem); - - foreach (var group in this.OrderBy(x => x.Key)) - { - firstItem = group.Value.FirstOrDefault(); - - if (firstItem != null) - { - return new SettingPageSearchResult() { Group = group.Key, Item = firstItem }; - } - } - - return null; - } - - /// - /// Returns all setting pages that are in the given group. - /// - /// The group. - /// A listing of all pages in the same group. - public List GetPages(string group) - { - if (ContainsKey(group)) - { - return this[group]; - } - - return null; - } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemSection.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemSection.cs deleted file mode 100644 index 94fc3ce0..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageDictionaryItemSection.cs +++ /dev/null @@ -1,102 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebUI.WebAttribute; - -namespace WebExpress.WebUI.SettingPage -{ - public class SettingPageDictionaryItemSection : Dictionary - { - /// - /// Adds an item. - /// - /// The section. - /// The group. - /// The item to insert. - public void AddPage(SettingSection section, string group, SettingPageDictionaryItem item) - { - // register Section - if (!ContainsKey(section)) - { - Add(section, new SettingPageDictionaryItemGroup()); - } - - this[section].AddPage(group, item); - } - - /// - /// Searches for an item based on its id. - /// - /// The setting site id. - /// The setting page found or null. - public SettingPageSearchResult FindPage(string pageId) - { - foreach (var v in this) - { - var path = v.Value.FindPage(pageId); - if (path != null) - { - path.Section = v.Key; - return path; - } - } - - return null; - } - - /// - /// Returns the first setting page. - /// - /// The first setting page. - public SettingPageSearchResult FindFirstPage() - { - var firstPage = default(SettingPageSearchResult); - - if (ContainsKey(SettingSection.Preferences)) - { - firstPage = this[SettingSection.Preferences].FindFirstPage(); - if (firstPage != null) - { - firstPage.Section = SettingSection.Preferences; - - return firstPage; - } - } - else if (ContainsKey(SettingSection.Primary)) - { - firstPage = this[SettingSection.Primary].FindFirstPage(); - if (firstPage != null) - { - firstPage.Section = SettingSection.Primary; - - return firstPage; - } - } - else if (ContainsKey(SettingSection.Secondary)) - { - firstPage = this[SettingSection.Secondary].FindFirstPage(); - if (firstPage != null) - { - firstPage.Section = SettingSection.Secondary; - - return firstPage; - } - } - - return firstPage; - } - - /// - /// Returns a groups that are in the given section. - /// - /// The section. - /// A group in the same section. - public SettingPageDictionaryItemGroup GetGroup(SettingSection section) - { - if (ContainsKey(section)) - { - return this[section]; - } - - return null; - } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs deleted file mode 100644 index b566e673..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageManager.cs +++ /dev/null @@ -1,275 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebModule; -using WebExpress.WebCore.WebPlugin; -using WebExpress.WebCore.WebResource; -using WebExpress.WebUI.WebAttribute; -using WebExpress.WebUI.WebControl; -using WebExpress.WebUI.WebSettingPage; - -namespace WebExpress.WebUI.SettingPage -{ - /// - /// Management of settings pages. - /// - public sealed class SettingPageManager : IComponentPlugin - { - /// - /// An event that fires when an setting page is added. - /// - public event EventHandler AddSettingPage; - - /// - /// An event that fires when an setting page is removed. - /// - public event EventHandler RemoveSettingPage; - - /// - /// Returns the reference to the context of the host. - /// - public IHttpServerContext HttpServerContext { get; private set; } - - /// - /// Returns the directory where the components are listed. - /// - private SettingPageDictionary Dictionary { get; } = new SettingPageDictionary(); - - /// - /// Initializes a new instance of the class. - /// - internal SettingPageManager() - { - ComponentManager.PluginManager.AddPlugin += (s, pluginContext) => - { - Register(pluginContext); - }; - - ComponentManager.PluginManager.RemovePlugin += (s, pluginContext) => - { - Remove(pluginContext); - }; - - //ComponentManager.ModuleManager.AddModule += (sender, moduleContext) => - //{ - // AssignToModule(moduleContext); - //}; - - //ComponentManager.ModuleManager.RemoveModule += (sender, moduleContext) => - //{ - // DetachFromModule(moduleContext); - //}; - } - - /// - /// Initialization - /// - /// The reference to the context of the host. - public void Initialization(IHttpServerContext context) - { - HttpServerContext = context; - - HttpServerContext.Log.Debug(InternationalizationManager.I18N("webexpress.webapp:pagesettingmanager.initialization")); - } - - /// - /// Discovers and registers entries from the specified plugin. - /// - /// A context of a plugin whose elements are to be registered. - public void Register(IPluginContext pluginContext) - { - foreach (var settingPageType in pluginContext.Assembly.GetTypes() - .Where(x => x.IsClass && x.IsSealed && (x.GetInterfaces().Contains(typeof(IPageSetting))))) - { - var id = settingPageType.FullName?.ToLower(); - var context = default(string); - var group = default(string); - var section = SettingSection.Primary; - var moduleId = default(string); - var hide = false; - var icon = default(PropertyIcon); - - // determining attributes - foreach (var customAttribute in settingPageType.CustomAttributes - .Where(x => x.AttributeType.GetInterfaces().Contains(typeof(IResourceAttribute)))) - { - if (customAttribute.AttributeType == typeof(SettingContextAttribute)) - { - context = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString(); - } - else if (customAttribute.AttributeType == typeof(SettingGroupAttribute)) - { - group = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString(); - } - else if (customAttribute.AttributeType == typeof(SettingSectionAttribute)) - { - section = (SettingSection)Enum.Parse(typeof(SettingSection), customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString()); - } - else if (customAttribute.AttributeType == typeof(SettingHideAttribute)) - { - hide = true; - } - else if (customAttribute.AttributeType.Name == typeof(ModuleAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ModuleAttribute<>).Namespace) - { - moduleId = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower(); - } - else if (customAttribute.AttributeType == typeof(SettingIconAttribute)) - { - var iconAttribute = customAttribute.ConstructorArguments.FirstOrDefault().Value; - icon = iconAttribute?.GetType() == typeof(int) ? - new PropertyIcon((TypeIcon)Enum.Parse(typeof(TypeIcon), iconAttribute?.ToString())) : - new PropertyIcon(iconAttribute?.ToString()); - } - } - - if (string.IsNullOrEmpty(id)) - { - HttpServerContext.Log.Warning(InternationalizationManager.I18N - ( - "webexpress.webapp:pagesettingmanager.idless", - pluginContext.PluginId - )); - - continue; - } - - if (string.IsNullOrEmpty(moduleId)) - { - HttpServerContext.Log.Warning(InternationalizationManager.I18N - ( - "webexpress.webapp:pagesettingmanager.moduleless", - id, - pluginContext.PluginId - )); - - continue; - } - - // Create meta information of the setting page - var page = new SettingPageDictionaryItem() - { - Id = id, - ModuleId = moduleId, - ResourceId = id, - Icon = icon, - Hide = hide, - Context = context, - Section = section, - Group = group - }; - - // Insert the settings page into the dictionary - Dictionary.AddPage(pluginContext, page); - - // Logging - var log = new List - { - InternationalizationManager.I18N("webexpress.webapp:pagesettingmanager.register"), - " ModuleId = " + page?.ModuleId, - " SettingContext = " + context ?? "null", - " SettingSection = " + section.ToString(), - " SettingGroup = " + group ?? "null", - " SettingPage.Id = " + page?.Id ?? "null", - " SettingPage.Hide = " + (page?.Hide != null ? page?.Hide.ToString() : "null") - }; - - HttpServerContext.Log.Debug(string.Join(Environment.NewLine, log)); - } - } - - /// - /// Adds the component-key-value pairs from the specified plugin. - /// - /// A list with plugin contexts that contain the components. - public void Register(IEnumerable pluginContexts) - { - foreach (var pluginContext in pluginContexts) - { - Register(pluginContext); - } - } - - /// - /// Removes all elemets associated with the specified plugin context. - /// - /// The context of the plugin that contains the elemets to remove. - public void Remove(IPluginContext pluginContext) - { - Dictionary.Remove(pluginContext); - } - - /// - /// Raises the AddSettingPage event. - /// - /// The resource context. - private void OnAddSettingPage(IResourceContext resourceContext) - { - AddSettingPage?.Invoke(this, resourceContext); - } - - /// - /// Raises the RemoveSettingPage event. - /// - /// The resource context. - private void OnRemoveSettingPage(IResourceContext resourceContext) - { - RemoveSettingPage?.Invoke(this, resourceContext); - } - - /// - /// Searches for a page by its id. - /// - /// The application context. - /// the module context. - /// The page. - /// The page found, or null. - /// - public SettingPageSearchResult FindPage(IApplicationContext applicationContext, IModuleContext moduleContext, string pageId) - { - return Dictionary.FindPage(applicationContext, moduleContext, pageId); - } - - /// - /// Returns all contexts. - /// - /// The application context. - /// A listing of all contexts. - /// - public IEnumerable GetContexts(IApplicationContext applicationContext) - { - return Dictionary.GetContexts(applicationContext.ApplicationId); - } - - /// - /// Returns all sections that have the same setting context. - /// - /// The application context. - /// The context. - /// A listing of all sections of the same context. - /// - public IEnumerable GetSections(IApplicationContext applicationContext, string context) - { - return Dictionary.GetSections(applicationContext.ApplicationId, context); - } - - /// - /// Information about the component is collected and prepared for output in the log. - /// - /// The context of the plugin. - /// A list of log entries. - /// The shaft deep. - public void PrepareForLog(IPluginContext pluginContext, IList output, int deep) - { - output.Add - ( - string.Empty.PadRight(deep) + - InternationalizationManager.I18N("webexpress.webui:settingpagemanager.titel") - ); - } - } -} \ No newline at end of file diff --git a/src/WebExpress.WebUI/WebSettingPage/SettingPageSearchResult.cs b/src/WebExpress.WebUI/WebSettingPage/SettingPageSearchResult.cs deleted file mode 100644 index a04f3cd7..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/SettingPageSearchResult.cs +++ /dev/null @@ -1,27 +0,0 @@ -ο»Ώusing WebExpress.WebUI.WebAttribute; - -namespace WebExpress.WebUI.SettingPage -{ - public class SettingPageSearchResult - { - /// - /// Returns the setting context. - /// - public string Context { get; internal set; } - - /// - /// Returns the section. - /// - public SettingSection Section { get; internal set; } - - /// - /// Returns the group. - /// - public string Group { get; internal set; } - - /// - /// A list of all currently existing setting contexts that can be accessed through the settings page. - /// - public SettingPageDictionaryItem Item { get; internal set; } - } -} diff --git a/src/WebExpress.WebUI/WebSettingPage/TimeSpanConverter.cs b/src/WebExpress.WebUI/WebSettingPage/TimeSpanConverter.cs deleted file mode 100644 index b1b105d2..00000000 --- a/src/WebExpress.WebUI/WebSettingPage/TimeSpanConverter.cs +++ /dev/null @@ -1,31 +0,0 @@ -ο»Ώusing System; - -namespace WebExpress.WebUI.WebSettingPage -{ - public class TimeSpanConverter - { - public object Convert(object value, Type targetType, object parameter, string language) - { - if (value == null) - { - return null; - } - - var ts = TimeSpan.Parse(value.ToString()); - return string.Format - ( - "{0}d {1:D2}h {2:D2}m {3:D2}s {4:D2}ms", - ts.Days, - ts.Hours, - ts.Minutes, - ts.Seconds, - ts.Milliseconds - ); - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } - } -} From 81423a7decc7608f64f64575d0332e9852fe2ac6 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 14 Dec 2024 18:49:15 +0100 Subject: [PATCH 13/59] partial implementation of new functionality - added initial 20% of new features - removed outdated 80% of old functionality - marked as a work-in-progress for continued development --- .../Control/UnitTestControlAlert.cs | 81 -- .../Control/UnitTestControlForm.cs | 167 --- .../Control/UnitTestControlFormInline.cs | 141 -- .../Control/UnitTestControlList.cs | 111 -- .../Control/UnitTestControlModalForm.cs | 155 --- .../Fixture/NonParallelTestsCollection.cs | 11 + .../Fixture/UnitTestControlFixture.cs | 252 ++-- src/WebExpress.WebUI.Test/TestApplication.cs | 19 +- .../TestFragmentControlButtonLink.cs | 22 + .../TestFragmentControlImage.cs | 22 + .../TestFragmentControlLink.cs | 22 + .../TestFragmentControlList.cs | 23 + .../TestFragmentControlText.cs | 24 + src/WebExpress.WebUI.Test/TestModule.cs | 40 - src/WebExpress.WebUI.Test/TestPage.cs | 75 +- src/WebExpress.WebUI.Test/TestPlugin.cs | 9 +- src/WebExpress.WebUI.Test/TestSectionA.cs | 11 + src/WebExpress.WebUI.Test/TestSectionB.cs | 11 + src/WebExpress.WebUI.Test/TestSectionC.cs | 11 + src/WebExpress.WebUI.Test/TestSectionD.cs | 11 + src/WebExpress.WebUI.Test/TestSectionE.cs | 11 + src/WebExpress.WebUI.Test/TestSectionF.cs | 11 + .../WebControl/UnitTestControlAlert.cs | 77 ++ .../WebControl/UnitTestControlButton.cs | 199 +++ .../WebControl/UnitTestControlButtonLink.cs | 223 +++ .../WebControl/UnitTestControlForm.cs | 166 +++ .../WebControl/UnitTestControlFormInline.cs | 140 ++ .../UnitTestControlFormItemInputRadio.cs | 45 +- .../WebControl/UnitTestControlIcon.cs | 127 ++ .../WebControl/UnitTestControlImage.cs | 126 ++ .../WebControl/UnitTestControlLink.cs | 195 +++ .../WebControl/UnitTestControlList.cs | 90 ++ .../WebControl/UnitTestControlModal.cs | 56 + .../WebControl/UnitTestControlModalForm.cs | 154 +++ .../WebControl/UnitTestControlText.cs | 58 + .../WebExpress.WebUI.Test.csproj | 2 +- .../WebFragment/FragmentHeaderPrimary.cs | 27 - .../WebFragment/UnitTestFragmentManager.cs | 62 + .../WebPage/UnitTestFragmentManager.cs | 34 + src/WebExpress.WebUI/Internationalization/de | 12 - src/WebExpress.WebUI/Internationalization/en | 12 - .../WebAttribute/IComponentAttribute.cs | 9 - .../WebAttribute/OrderAttribute.cs | 17 - .../WebAttribute/SectionAttribute.cs | 17 - .../WebAttribute/SettingContextAttribute.cs | 21 - .../WebAttribute/SettingGroupAttribute.cs | 21 - .../WebAttribute/SettingHideAttribute.cs | 18 - .../WebAttribute/SettingIconAttribute.cs | 29 - .../WebComponent/ComponentHubUI.cs | 25 + .../WebComponent/IComponentHubUI.cs | 11 + src/WebExpress.WebUI/WebControl/Control.cs | 29 +- .../WebControl/ControlArlert.cs | 10 +- .../WebControl/ControlAttribute.cs | 162 +-- .../WebControl/ControlAvatar.cs | 164 +-- .../WebControl/ControlBadge.cs | 230 +-- .../WebControl/ControlBreadcrumb.cs | 324 ++--- .../WebControl/ControlButton.cs | 39 +- .../WebControl/ControlButtonLink.cs | 46 +- .../WebControl/ControlCanvas.cs | 166 +-- .../WebControl/ControlCardCounter.cs | 172 +-- .../WebControl/ControlCarousel.cs | 230 +-- .../WebControl/ControlCarouselItem.cs | 54 +- .../WebControl/ControlChart.cs | 335 +++-- .../WebControl/ControlChartDataset.cs | 74 +- .../WebControl/ControlDropdown.cs | 636 ++++----- .../WebControl/ControlDropdownItemDivider.cs | 78 +- .../WebControl/ControlDropdownItemHeader.cs | 106 +- .../WebControl/ControlDropdownItemLink.cs | 158 +-- .../WebControl/ControlForm.cs | 1231 ++++++++--------- .../WebControl/ControlFormItem.cs | 95 +- .../WebControl/ControlFormItemButton.cs | 330 ++--- .../WebControl/ControlFormItemButtonSubmit.cs | 44 +- .../WebControl/ControlFormItemGroup.cs | 198 +-- .../WebControl/ControlFormItemGroupColumn.cs | 258 ++-- .../ControlFormItemGroupColumnHorizontal.cs | 284 ++-- .../ControlFormItemGroupColumnMix.cs | 288 ++-- .../ControlFormItemGroupColumnVertical.cs | 278 ++-- .../ControlFormItemGroupHorizontal.cs | 246 ++-- .../WebControl/ControlFormItemGroupMix.cs | 248 ++-- .../ControlFormItemGroupVertical.cs | 202 +-- .../WebControl/ControlFormItemHelpText.cs | 122 +- .../WebControl/ControlFormItemInput.cs | 304 ++-- .../ControlFormItemInputCheckbox.cs | 156 +-- .../ControlFormItemInputComboBox.cs | 230 +-- .../ControlFormItemInputComboBoxItem.cs | 90 +- .../ControlFormItemInputDatepicker.cs | 261 ++-- .../WebControl/ControlFormItemInputFile.cs | 198 +-- .../WebControl/ControlFormItemInputGroup.cs | 146 +- .../WebControl/ControlFormItemInputHidden.cs | 100 +- .../WebControl/ControlFormItemInputMove.cs | 298 ++-- .../WebControl/ControlFormItemInputRadio.cs | 256 ++-- .../ControlFormItemInputSelection.cs | 320 ++--- .../ControlFormItemInputSelectionItem.cs | 84 +- .../WebControl/ControlFormItemInputTextBox.cs | 420 +++--- .../WebControl/ControlFormItemLabel.cs | 122 +- .../WebControl/ControlFormItemPanel.cs | 136 +- .../WebControl/ControlFormItemPrepend.cs | 130 +- .../WebControl/ControlFormItemStaticText.cs | 104 +- .../WebControl/ControlHtml.cs | 102 +- .../WebControl/ControlIcon.cs | 21 +- .../WebControl/ControlImage.cs | 28 +- .../WebControl/ControlLine.cs | 110 +- .../WebControl/ControlLink.cs | 97 +- .../WebControl/ControlLinkList.cs | 136 +- .../WebControl/ControlList.cs | 89 +- .../WebControl/ControlListItem.cs | 63 +- .../WebControl/ControlListItemButton.cs | 156 +-- .../WebControl/ControlListItemLink.cs | 390 +++--- .../WebControl/ControlModal.cs | 65 +- .../WebControl/ControlModalForm.cs | 440 +++--- .../WebControl/ControlMultipleProgressBar.cs | 252 ++-- .../ControlMultipleProgressBarItem.cs | 44 +- .../WebControl/ControlNavigation.cs | 410 +++--- .../ControlNavigationItemDropdown.cs | 50 +- .../WebControl/ControlNavigationItemHeader.cs | 92 +- .../WebControl/ControlNavigationItemLink.cs | 68 +- .../WebControl/ControlPagination.cs | 420 +++--- .../WebControl/ControlPanel.cs | 202 +-- .../WebControl/ControlPanelCallout.cs | 150 +- .../WebControl/ControlPanelCard.cs | 288 ++-- .../WebControl/ControlPanelCenter.cs | 118 +- .../WebControl/ControlPanelDialog.cs | 42 +- .../WebControl/ControlPanelFilter.cs | 42 +- .../WebControl/ControlPanelFlexbox.cs | 202 +-- .../WebControl/ControlPanelFooter.cs | 122 +- .../WebControl/ControlPanelGrid.cs | 88 +- .../WebControl/ControlPanelHeader.cs | 148 +- .../WebControl/ControlPanelMain.cs | 68 +- .../WebControl/ControlPanelMedia.cs | 166 +-- .../WebControl/ControlPanelNavbar.cs | 120 +- .../WebControl/ControlPanelSplit.cs | 326 +++-- .../WebControl/ControlPanelToast.cs | 28 +- .../WebControl/ControlPanelTool.cs | 152 +- .../WebControl/ControlProgressBar.cs | 308 ++--- .../WebControl/ControlSplitButton.cs | 488 +++---- .../ControlSplitButtonItemDivider.cs | 78 +- .../ControlSplitButtonItemHeader.cs | 106 +- .../WebControl/ControlSplitButtonItemLink.cs | 64 +- .../WebControl/ControlSplitButtonLink.cs | 456 +++--- .../WebControl/ControlTable.cs | 362 ++--- .../WebControl/ControlTableColumn.cs | 204 +-- .../WebControl/ControlTableRow.cs | 144 +- src/WebExpress.WebUI/WebControl/ControlTag.cs | 330 ++--- .../WebControl/ControlTagCloud.cs | 86 +- .../WebControl/ControlText.cs | 25 +- .../WebControl/ControlTimeline.cs | 120 +- .../WebControl/ControlTimelineComment.cs | 284 ++-- .../WebControl/ControlTimelineItem.cs | 416 +++--- .../WebControl/ControlToolbar.cs | 234 ++-- .../WebControl/ControlToolbarItemButton.cs | 46 +- .../WebControl/ControlToolbarItemSeperator.cs | 28 +- .../WebControl/ControlTree.cs | 306 ++-- .../WebControl/ControlTreeItem.cs | 372 ++--- .../WebControl/ControlTreeItemLink.cs | 480 +++---- .../WebControl/FormEventArgs.cs | 40 +- src/WebExpress.WebUI/WebControl/IControl.cs | 13 +- .../WebControl/IControlForm.cs | 150 +- .../WebControl/IFormValidation.cs | 48 +- .../WebControl/PropertyModal.cs | 31 +- .../WebControl/RenderContextForm.cs | 128 +- .../WebControl/RenderContextFormGroup.cs | 62 +- .../WebControl/TypeColorButton.cs | 6 + .../WebControl/ValidationEventArgs.cs | 48 +- src/WebExpress.WebUI/WebExUI.cs | 25 + src/WebExpress.WebUI/WebExpress.WebUI.csproj | 3 +- .../WebFragment/FragmentCacheItem.cs | 86 -- .../WebFragment/FragmentComparer.cs | 40 - .../WebFragment/FragmentContext.cs | 52 - .../WebFragment/FragmentControlButtonLink.cs | 29 +- .../FragmentControlDropdownItemLink.cs | 58 +- .../WebFragment/FragmentControlImage.cs | 30 +- .../WebFragment/FragmentControlLink.cs | 27 +- .../WebFragment/FragmentControlList.cs | 29 +- .../WebFragment/FragmentControlModalForm.cs | 58 +- .../FragmentControlNavigationItemLink.cs | 58 +- .../WebFragment/FragmentControlPanel.cs | 58 +- .../FragmentControlPanelFlexbox.cs | 58 +- .../WebFragment/FragmentControlPanelTool.cs | 58 +- .../FragmentControlSplitButtonItemLink.cs | 58 +- .../WebFragment/FragmentControlText.cs | 29 +- .../WebFragment/FragmentControlTree.cs | 58 +- .../WebFragment/FragmentItemComparer.cs | 31 - .../WebFragment/FragmentManager.cs | 464 ------- src/WebExpress.WebUI/WebFragment/IFragment.cs | 20 - .../WebFragment/IFragmentContext.cs | 40 - .../WebFragment/IFragmentControl.cs | 18 + .../WebFragment/IFragmentDynamic.cs | 27 - .../WebFragment/IFragmentManager.cs | 57 - .../WebFragment/Model/FragmentDictionary.cs | 151 -- .../WebFragment/Model/FragmentItem.cs | 75 - .../WebPage/IRenderControlContext.cs | 23 + src/WebExpress.WebUI/WebPage/PageControl.cs | 114 +- .../WebPage/RenderContextControl.cs | 45 - .../WebPage/RenderControlContext.cs | 39 + .../WebPage/VisualTreeControl.cs | 85 +- .../WebSection/SectionControl.cs | 38 - 196 files changed, 13106 insertions(+), 13098 deletions(-) delete mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs delete mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs delete mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs delete mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs delete mode 100644 src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs create mode 100644 src/WebExpress.WebUI.Test/Fixture/NonParallelTestsCollection.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlImage.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlList.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlText.cs delete mode 100644 src/WebExpress.WebUI.Test/TestModule.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionA.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionB.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionC.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionD.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionE.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionF.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs rename src/WebExpress.WebUI.Test/{Control => WebControl}/UnitTestControlFormItemInputRadio.cs (52%) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs delete mode 100644 src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs create mode 100644 src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs create mode 100644 src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/IComponentAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs create mode 100644 src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs create mode 100644 src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs create mode 100644 src/WebExpress.WebUI/WebExUI.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentComparer.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentContext.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/FragmentManager.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/IFragment.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/IFragmentContext.cs create mode 100644 src/WebExpress.WebUI/WebFragment/IFragmentControl.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/IFragmentDynamic.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/IFragmentManager.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs delete mode 100644 src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs create mode 100644 src/WebExpress.WebUI/WebPage/IRenderControlContext.cs delete mode 100644 src/WebExpress.WebUI/WebPage/RenderContextControl.cs create mode 100644 src/WebExpress.WebUI/WebPage/RenderControlContext.cs delete mode 100644 src/WebExpress.WebUI/WebSection/SectionControl.cs diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs deleted file mode 100644 index 3ee85bf9..00000000 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlAlert.cs +++ /dev/null @@ -1,81 +0,0 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; - -namespace WebExpress.WebUI.Test.Control -{ - /// - /// Tests the alert control. - /// - public class UnitTestControlAlert : IClassFixture - { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlAlert(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty alert. - /// - [Fact] - public void EmptyAlert() - { - // preconditions - var context = new WebCore.WebPage.RenderContext(); - var control = new ControlAlert(); - - // test execution - var html = control.Render(context); - - Assert.Equal(@"
          ", html.Trim()); - } - - /// - /// Tests a alert. - /// - [Fact] - public void AlertWithId() - { - // preconditions - var context = new WebCore.WebPage.RenderContext(); - var control = new ControlAlert("alertid"); - - // test execution - var html = control.Render(context); - - Assert.Contains(@"alertid", html.Trim()); - } - - /// - /// Tests a alert. - /// - [Fact] - public void AlertWithText() - { - // preconditions - var context = new WebCore.WebPage.RenderContext(); - var control = new ControlAlert() { Text = "abc" }; - - // test execution - var html = control.Render(context); - - Assert.Contains(@"abc", html.Trim()); - } - } -} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs deleted file mode 100644 index 2e88deb9..00000000 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlForm.cs +++ /dev/null @@ -1,167 +0,0 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; - -namespace WebExpress.WebUI.Test.Control -{ - /// - /// Tests the form control. - /// - public class UnitTestControlForm : IClassFixture - { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlForm(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty form. - /// - [Fact] - public void EmptyForm() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm(); - - var html = control.Render(context); - - // test execution - Assert.StartsWith("
          - /// Tests a simple form with id. - ///
          - [Fact] - public void EmptyFormWithId() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm("form"); - - var html = control.Render(context); - - // test execution - Assert.StartsWith(@" - /// Tests a simple form. - /// The control elements are added during rendering. - ///
          - [Fact] - public void SimpleFormAtRender() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm(); - var item = new ControlFormItemInputTextBox() { }; - - // test execution - var html = control.Render(context, [item]); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added when instantiating. - /// - [Fact] - public void SimpleFormAtInstancing() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlForm("form", item); - - // test execution - var html = control.Render(context); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added using add. - /// - [Fact] - public void SimpleFormAtAdd() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlForm("form"); - - control.Add(item); - - // test execution - var html = control.Render(context); - var str = html.ToString(); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a complex form. - /// - [Fact] - public void ComplexForm() - { - // preconditions - var expectedResult = Fixture.GetEmbeddedResource("ComplexForm.txt"); - var context = Fixture.CrerateContext(); - var item1 = new ControlFormItemInputTextBox() { Label = "Label1", Help = "Help1", Placeholder = "Placeholder1" }; - var item2 = new ControlFormItemInputTextBox() { Label = "Label2", Help = "Help2", Placeholder = "Placeholder2" }; - var submitButton = new ControlFormItemButtonSubmit("Submit"); - var control = new ControlForm("form", item1, item2); - control.AddPrimaryButton(submitButton); - - - // test execution - var html = control.Render(context); - var str = html.ToString(); - - // postconditions - expectedResult = expectedResult.Replace("05c888e8-15f3-4be8-b765-0d7be63cc82b", control.FormId.Id); - expectedResult = expectedResult.Replace("974c6159-98e3-4ede-8bb5-6bc4d52e1770", control.SubmitType.Id); - - Assert.Equal(expectedResult.Trim(), str.Trim()); - } - } -} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs deleted file mode 100644 index 7598f96b..00000000 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormInline.cs +++ /dev/null @@ -1,141 +0,0 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; - -namespace WebExpress.WebUI.Test.Control -{ - /// - /// Tests the inline form control. - /// - public class UnitTestControlFormInline : IClassFixture - { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlFormInline(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty form. - /// - [Fact] - public void EmptyForm() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; - - var html = control.Render(context); - var str = html.ToString(); - - // test execution - Assert.StartsWith(@" - /// Tests a empty form. - ///
          - [Fact] - public void EmptyFormChangeSubmitText() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; - control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); - - var html = control.Render(context); - var str = html.ToString(); - - // test execution - Assert.Contains(@"sendbutton", html.Trim()); - } - - /// - /// Tests a simple form with id. - /// - [Fact] - public void EmptyFormWithId() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; - - var html = control.Render(context); - - // test execution - Assert.StartsWith(@" - /// Tests a simple form. - /// The control elements are added during rendering. - ///
          - [Fact] - public void SimpleFormAtRender() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; - var item = new ControlFormItemInputTextBox() { }; - - // test execution - var html = control.Render(context, [item]); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added when instantiating. - /// - [Fact] - public void SimpleFormAtInstancing() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlForm("form", item) { FormLayout = TypeLayoutForm.Inline }; - - // test execution - var html = control.Render(context); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added using add. - /// - [Fact] - public void SimpleFormAtAdd() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; - - control.Add(item); - - // test execution - var html = control.Render(context); - var str = html.ToString(); - - Assert.Contains(@"", html.Trim()); - } - } -} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs deleted file mode 100644 index ab3a54d6..00000000 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlList.cs +++ /dev/null @@ -1,111 +0,0 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; - -namespace WebExpress.WebUI.Test.Control -{ - /// - /// Tests the list control. - /// - public class UnitTestControlList : IClassFixture - { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlList(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty list. - /// - [Fact] - public void EmptyList() - { - // preconditions - var context = new WebCore.WebPage.RenderContext(); - var control = new ControlList(); - - // test execution - Assert.Equal("
            ", control.Render(context).Trim()); - } - - /// - /// Tests a empty list. - /// - [Fact] - public void EmptyListGroup() - { - // preconditions - var context = new WebCore.WebPage.RenderContext(); - var control = new ControlList() { Layout = TypeLayoutList.Group }; - - // test execution - Assert.Equal("
              ", control.Render(context).Trim()); - } - - /// - /// Tests a list. - /// The list elements are added during rendering. - /// - [Fact] - public void SimpleListAtRender() - { - // preconditions - var context = new WebCore.WebPage.RenderContext() { }; - var item = new ControlListItem(new ControlText() { Text = "abc" }); - var control = new ControlList(); - - // test execution - Assert.Equal("
              • abc
              ", control.Render(context, [item]).Trim()); - } - - /// - /// Tests a list. - /// The list elements are added using add. - /// - [Fact] - public void SimpleListAtInstancing() - { - // preconditions - var context = new WebCore.WebPage.RenderContext() { }; - var item = new ControlListItem(new ControlText() { Text = "abc" }); - var control = new ControlList(item); - - // test execution - Assert.Equal("
              • abc
              ", control.Render(context).Trim()); - } - - /// - /// Tests a list. - /// The list elements are added using add. - /// - [Fact] - public void SimpleListAtAdd() - { - // preconditions - var context = new WebCore.WebPage.RenderContext() { }; - var item = new ControlListItem(new ControlText() { Text = "abc" }); - var control = new ControlList(); - - control.Add(item); - - // test execution - Assert.Equal("
              • abc
              ", control.Render(context).Trim()); - } - } -} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs b/src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs deleted file mode 100644 index cae74398..00000000 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlModalForm.cs +++ /dev/null @@ -1,155 +0,0 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; - -namespace WebExpress.WebUI.Test.Control -{ - /// - /// Tests the modal form control. - /// - public class UnitTestControlModalForm : IClassFixture - { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlModalForm(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty form. - /// - [Fact] - public void EmptyForm() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlModalForm(); - - var html = control.Render(context); - var str = html.ToString(); - - // test execution - Assert.StartsWith(" - /// Tests a simple form with header. - ///
              - [Fact] - public void EmptyFormWithHeaderAtInstancing() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlModalForm("form", "header"); - - var html = control.Render(context); - - // test execution - Assert.Contains(@"

              header

              ", html.Trim()); - } - - /// - /// Tests a simple form with header. - /// - [Fact] - public void EmptyFormWithHeaderAtProperty() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlModalForm("form") { Header = "header" }; - - var html = control.Render(context); - - // test execution - Assert.Contains(@"

              header

              ", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added during rendering. - /// - [Fact] - public void SimpleFormAtRender() - { - // preconditions - var context = Fixture.CrerateContext(); - var control = new ControlModalForm(); - var item = new ControlFormItemInputTextBox() { }; - - // test execution - var html = control.Render(context, [item]); - //var str = html.ToString(); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added when instantiating. - /// - [Fact] - public void SimpleFormAtInstancing() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlModalForm("form", item); - - // test execution - var html = control.Render(context); - - Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added using add. - /// - [Fact] - public void SimpleFormAtAdd() - { - // preconditions - var context = Fixture.CrerateContext(); - var item = new ControlFormItemInputTextBox() { }; - var control = new ControlModalForm("form"); - - control.Add(item); - - // test execution - var html = control.Render(context); - - Assert.Contains(@"", html.Trim()); - } - } -} diff --git a/src/WebExpress.WebUI.Test/Fixture/NonParallelTestsCollection.cs b/src/WebExpress.WebUI.Test/Fixture/NonParallelTestsCollection.cs new file mode 100644 index 00000000..67e57bc5 --- /dev/null +++ b/src/WebExpress.WebUI.Test/Fixture/NonParallelTestsCollection.cs @@ -0,0 +1,11 @@ +ο»Ώnamespace WebExpress.WebUI.Test.Fixture +{ + /// + /// Defines a collection of tests that should not be run in parallel. + /// + [CollectionDefinition("NonParallelTests", DisableParallelization = true)] + public class NonParallelTestsCollection : ICollectionFixture + { + + } +} diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index d1470572..266aed49 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -1,71 +1,138 @@ ο»Ώusing Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; +using System.Globalization; using System.Net; using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; using WebExpress.WebCore; +using WebExpress.WebCore.WebApplication; using WebExpress.WebCore.WebComponent; +using WebExpress.WebCore.WebEndpoint; using WebExpress.WebCore.WebLog; using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebModule; using WebExpress.WebCore.WebPage; using WebExpress.WebCore.WebPlugin; -using WebExpress.WebCore.WebResource; -using WebExpress.WebUI.WebControl; +using WebExpress.WebCore.WebUri; +using WebExpress.WebUI.WebComponent; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.Fixture { - public class UnitTestControlFixture : IDisposable + /// + /// A fixture class for unit tests, providing various mock objects and utility methods. + /// + public partial class UnitTestControlFixture : IDisposable { - /// - /// Returns a guard to protect against concurrent access. - /// - private static object guard = new object(); + private static readonly string[] _separator = ["\r\n", "\r", "\n"]; + + [GeneratedRegex(@">\s+<")] + private static partial Regex WhitespaceRegex(); /// /// Initializes a new instance of the class and boot the component manager. /// public UnitTestControlFixture() { - lock (guard) + } + + /// + /// Create a fake server context. + /// + /// The server context. + public static IHttpServerContext CreateHttpServerContextMock() + { + return new HttpServerContext + ( + "localhost", + [], + "", + Environment.CurrentDirectory, + Environment.CurrentDirectory, + Environment.CurrentDirectory, + new UriResource("/server"), + CultureInfo.GetCultureInfo("en"), + new Log() { LogMode = LogMode.Off }, + null + ); + } + + /// + /// Create a component hub. + /// + /// The component hub. + public static ComponentHub CreateComponentHubMock() + { + var ctorComponentHub = typeof(ComponentHubUI).GetConstructor + ( + BindingFlags.NonPublic | BindingFlags.Instance, + null, + [typeof(HttpServerContext)], + null + ); + + var componentHub = (ComponentHub)ctorComponentHub.Invoke([CreateHttpServerContextMock()]); + + // set static field in the webex class + var type = typeof(WebEx); + var field = type.GetField("_componentHub", BindingFlags.Static | BindingFlags.NonPublic); + + field.SetValue(null, componentHub); + + return componentHub; + } + + /// + /// Create a component hub and register the plugins. + /// + /// The component hub. + public static ComponentHub CreateAndRegisterComponentHubMock() + { + var componentHub = CreateComponentHubMock(); + var pluginManager = componentHub.PluginManager as PluginManager; + + var registerMethod = pluginManager.GetType().GetMethod("Register", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, []); + registerMethod.Invoke(pluginManager, null); + + return componentHub; + } + + /// + /// Create a fake request. + /// + /// The content of the request. + /// The URI of the request. + /// A fake request for testing. + public static Request CrerateRequestMock(string content = "", string uri = "") + { + var context = CreateHttpContextMock(content); + + var request = context.Request; + + if (!string.IsNullOrEmpty(uri)) { - if (ComponentManager.PluginManager != null) - { - return; - } - - var initializationComponentManager = typeof(ComponentManager).GetMethod("Initialization", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, [typeof(IHttpServerContext)]); - var registerPluginManager = typeof(PluginManager).GetMethod("Register", BindingFlags.NonPublic | BindingFlags.Instance, [typeof(Assembly), typeof(PluginLoadContext)]); - var serverContext = new HttpServerContext - ( - "localhost", - [], - "", - "", - "", - "", - null, - null, - new Log() { LogMode = LogMode.Off }, - null - ); - - initializationComponentManager.Invoke(null, [serverContext]); - - registerPluginManager.Invoke(ComponentManager.PluginManager, [typeof(Plugin).Assembly, null]); - registerPluginManager.Invoke(ComponentManager.PluginManager, [GetType().Assembly, null]); + var uriProperty = typeof(Request).GetProperty("Uri", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + uriProperty.SetValue(request, new UriResource(uri)); } + + return request; } /// - /// Create a fake render context. + /// Create a fake http context. /// - /// A fake context for testing. - public RenderContext CrerateContext() + /// The content. + /// A fake http context for testing. + public static WebCore.WebMessage.HttpContext CreateHttpContextMock(string content = "") { - var ctorRequestHeaderFields = typeof(RequestHeaderFields).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection)], null); - var ctorRequest = typeof(Request).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection), typeof(IHttpServerContext), typeof(RequestHeaderFields)], null); + var ctorRequest = typeof(Request).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IFeatureCollection), typeof(RequestHeaderFields), typeof(IHttpServerContext)], null); var featureCollection = new FeatureCollection(); + var firstLine = content.Split('\n').FirstOrDefault(); + var lines = content.Split(_separator, StringSplitOptions.None); + var filteredLines = lines.Skip(1).TakeWhile(line => !string.IsNullOrWhiteSpace(line)); + var pos = content.Length > 0 ? content.IndexOf(filteredLines.LastOrDefault()) + filteredLines.LastOrDefault().Length + 4 : 0; + var innerContent = pos < content.Length ? content[pos..] : ""; + var contentBytes = Encoding.UTF8.GetBytes(innerContent); var requestFeature = new HttpRequestFeature { @@ -74,17 +141,31 @@ public RenderContext CrerateContext() ["Host"] = "localhost", ["Connection"] = "keep-alive", ["ContentType"] = "text/html", - ["ContentLength"] = "0", + ["ContentLength"] = innerContent.Length.ToString(), ["ContentLanguage"] = "en", ["ContentEncoding"] = "gzip, deflate, br, zstd", ["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", ["AcceptEncoding"] = "gzip, deflate, br, zstd", ["AcceptLanguage"] = "de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", ["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0", - ["Referer"] = "0HN50661TV8TP" - } + ["Referer"] = "0HN50661TV8TP", + ["Cookie"] = "session=AB333C76-E73F-45E0-85FD-123320D9B85F" + }, + Body = contentBytes.Length > 0 ? new MemoryStream(contentBytes) : null, + Method = firstLine.Split(' ')?.Where(x => !string.IsNullOrEmpty(x)).FirstOrDefault() ?? "GET", + RawTarget = firstLine.Split(' ')?.Skip(1)?.FirstOrDefault()?.Split('?')?.FirstOrDefault() ?? "/", + QueryString = "?" + firstLine.Split(' ')?.Skip(1)?.FirstOrDefault()?.Split('?')?.Skip(1)?.FirstOrDefault() ?? "", }; + foreach (var line in filteredLines) + { + var key = line.Split(':').FirstOrDefault().Trim(); + var value = line.Split(':').Skip(1).FirstOrDefault().Trim(); + requestFeature.Headers[key] = value; + } + + requestFeature.Headers.ContentLength = contentBytes.Length; + var requestIdentifierFeature = new HttpRequestIdentifierFeature { TraceIdentifier = "Ihr TraceIdentifier-Wert" @@ -103,53 +184,43 @@ public RenderContext CrerateContext() featureCollection.Set(requestIdentifierFeature); featureCollection.Set(connectionFeature); - var serverContext = new HttpServerContext - ( - "localhost", - [], - "", - "", - "", - "", - null, - null, - new Log() { LogMode = LogMode.Off }, - null - ); - var headers = (RequestHeaderFields)ctorRequestHeaderFields.Invoke([featureCollection]); - var request = (Request)ctorRequest.Invoke([featureCollection, serverContext, headers]); - var page = new TestPage(); - var visualTree = new VisualTreeControl(); - - page.Initialization(CrerateResourceContext()); + var componentManager = CreateComponentHubMock(); + var context = new WebCore.WebMessage.HttpContext(featureCollection, CreateHttpServerContextMock()); - return new RenderContext(page, request, visualTree); + return context; } /// - /// Create a fake render form context. + /// Creates a mock render context for unit testing. /// - /// A fake context for testing. - public RenderContextForm CrerateContextForm() + /// The application context. If null, defaults to null. + /// The scopes of the page. If null, defaults to null. + /// A mock render context for testing. + public static IRenderControlContext CrerateRenderContextMock(IApplicationContext applicationContext = null, IEnumerable scopes = null) { - return new RenderContextForm(CrerateContext(), new ControlForm()); + var request = CrerateRequestMock(); + + return new RenderControlContext(CreratePageContextMock(applicationContext, scopes), request); } /// - /// Create a fake resource context. + /// Create a fake page context for unit testing. /// + /// The application context. If null, defaults to null. + /// The scopes of the page. /// A fake context for testing. - public ResourceContext CrerateResourceContext() + public static PageContext CreratePageContextMock(IApplicationContext applicationContext = null, IEnumerable scopes = null) { - var ctorResourceContext = typeof(ResourceContext).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IModuleContext)], null); + var ctorPageContext = typeof(PageContext).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(IEndpointManager), typeof(Type), typeof(UriResource), typeof(IUriPathSegment)], null); - var moduleContext = ComponentManager.ModuleManager.Modules - .Where(x => x.ModuleId == typeof(TestModule).FullName.ToLower()) - .FirstOrDefault(); + var pageContext = (PageContext)ctorPageContext.Invoke([WebEx.ComponentHub.EndpointManager, null, new UriResource(), null]); + var applicationContextProperty = typeof(PageContext).GetProperty("ApplicationContext", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + applicationContextProperty.SetValue(pageContext, applicationContext); - var resourceContext = (ResourceContext)ctorResourceContext.Invoke([moduleContext]); + var scopesProperty = typeof(PageContext).GetProperty("Scopes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + scopesProperty.SetValue(pageContext, scopes); - return resourceContext; + return pageContext; } /// @@ -157,17 +228,39 @@ public ResourceContext CrerateResourceContext() /// /// The name of the resource file. /// The content of the embedded resource as a string. - public string GetEmbeddedResource(string fileName) + public static string GetEmbeddedResource(string fileName) { - var assembly = GetType().Assembly; + var assembly = typeof(UnitTestControlFixture).Assembly; var resourceName = assembly.GetManifestResourceNames() .FirstOrDefault(name => name.EndsWith(fileName, StringComparison.OrdinalIgnoreCase)); - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - using (StreamReader reader = new StreamReader(stream)) + using var stream = assembly.GetManifestResourceStream(resourceName); + using var memoryStream = new MemoryStream(); + stream.CopyTo(memoryStream); + var data = memoryStream.ToArray(); + + return Encoding.UTF8.GetString(data); + } + + /// + /// Removes all line breaks from the input string. + /// + /// The input string from which to remove line breaks. + /// A string with all line breaks removed. + public static string RemoveLineBreaks(string input) + { + if (string.IsNullOrEmpty(input)) { - return reader.ReadToEnd(); + return input; } + + // remove all line breaks + string result = input.Replace("\r\n", "").Replace("\r", "").Replace("\n", ""); + + // remove whitespace of any length between '>' and '<' + result = WhitespaceRegex().Replace(result, "><"); + + return result; } /// @@ -175,6 +268,7 @@ public string GetEmbeddedResource(string fileName) /// public void Dispose() { + GC.SuppressFinalize(this); } } } diff --git a/src/WebExpress.WebUI.Test/TestApplication.cs b/src/WebExpress.WebUI.Test/TestApplication.cs index af57dd8b..aa9b725a 100644 --- a/src/WebExpress.WebUI.Test/TestApplication.cs +++ b/src/WebExpress.WebUI.Test/TestApplication.cs @@ -6,18 +6,25 @@ namespace WebExpress.WebUI.Test /// /// A dummy application for testing purposes. /// - [Name("webexpress.webui.unittest")] - [Description("plugin.description")] + [Name("TestApplication")] + [Description("application.description")] [Icon("/assets/img/Logo.png")] - [Dependency("webexpress.webui")] + [ContextPath("/app")] + [AssetPath("/asset")] + [DataPath("/data")] public sealed class TestApplication : IApplication { /// - /// Initialization of the application. + /// Initializes a new instance of the class. /// - /// The application context. - public void Initialization(IApplicationContext applicationContext) + /// The application context, for testing the injection. + private TestApplication(IApplicationContext applicationContext) { + // test the injection + if (applicationContext == null) + { + throw new ArgumentNullException(nameof(applicationContext), "Parameter cannot be null or empty."); + } } /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs new file mode 100644 index 00000000..03f06241 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlButtonLink : FragmentControlButtonLink + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlButtonLink(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlButtonLink"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs b/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs new file mode 100644 index 00000000..ee738ba3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlImage : FragmentControlImage + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlImage(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Uri = "/a/b/c"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs new file mode 100644 index 00000000..fed17610 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlLink : FragmentControlLink + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlLink(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlLink"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlList.cs b/src/WebExpress.WebUI.Test/TestFragmentControlList.cs new file mode 100644 index 00000000..22d6b0f5 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlList.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlList : FragmentControlList + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlList(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Add(new ControlListItem()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlText.cs b/src/WebExpress.WebUI.Test/TestFragmentControlText.cs new file mode 100644 index 00000000..bad200f5 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlText.cs @@ -0,0 +1,24 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlText : FragmentControlText + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlText(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlText"; + Format = TypeFormatText.Paragraph; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestModule.cs b/src/WebExpress.WebUI.Test/TestModule.cs deleted file mode 100644 index 92792fb3..00000000 --- a/src/WebExpress.WebUI.Test/TestModule.cs +++ /dev/null @@ -1,40 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebModule; - -namespace WebExpress.WebUI.Test -{ - /// - /// A dummy module for testing purposes. - /// - [Application()] - [Name("module.name")] - [Description("module.description")] - [Icon("/assets/img/Logo.png")] - [AssetPath("/")] - [ContextPath("/")] - public sealed class TestModule : IModule - { - /// - /// Initialization of the module. - /// - /// The module context. - public void Initialization(IModuleContext moduleContext) - { - throw new NotImplementedException(); - } - - /// - /// Called when the plugin starts working. The call is concurrent. - /// - public void Run() - { - } - - /// - /// Release of unmanaged resources reserved during use. - /// - public void Dispose() - { - } - } -} diff --git a/src/WebExpress.WebUI.Test/TestPage.cs b/src/WebExpress.WebUI.Test/TestPage.cs index 21fb5ef2..a0e747e5 100644 --- a/src/WebExpress.WebUI.Test/TestPage.cs +++ b/src/WebExpress.WebUI.Test/TestPage.cs @@ -1,19 +1,17 @@ -ο»Ώusing System.Globalization; -using WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebMessage; +ο»Ώusing WebExpress.WebCore.WebAttribute; using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebResource; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test { /// /// A dummy class for testing purposes. /// - [Title("webindex:homepage.label")] - [Segment(null, "webindex:homepage.label")] + [Title("webindex:pagea.label")] + [Segment("pagea", "webindex:homepage.label")] [ContextPath(null)] - [Module] - public sealed class TestPage : IPage + public sealed class TestPage : IPage { /// /// Returns or sets the title of the page. @@ -21,61 +19,46 @@ public sealed class TestPage : IPage public string Title { get; set; } /// - /// Returns or sets the resource context. + /// Returns or sets the page context. /// - public IResourceContext ResourceContext { get; private set; } + public IPageContext PageContext { get; private set; } /// - /// Returns or sets the culture information. + /// Initialization of the page. Here, for example, managed resources can be loaded. /// - public CultureInfo Culture { get => CultureInfo.CurrentCulture; set => throw new NotImplementedException(); } - - /// - /// Instillation of the resource. Here, for example, managed resources can be loaded. - /// - /// The context of the resource. - public void Initialization(IResourceContext resourceContext) + /// The context of the page. + public TestPage(IPageContext pageContext) { - ResourceContext = resourceContext; - } + PageContext = pageContext; - /// - /// Post-processes the request and response. - /// - /// The request. - /// The response. - /// The processed response. - public Response PostProcess(Request request, Response response) - { - return null; + // test the injection + if (pageContext == null) + { + throw new ArgumentNullException(nameof(pageContext), "Parameter cannot be null or empty."); + } } /// - /// Pre-processes the request. + /// Processing of the page. /// - /// The request. - public void PreProcess(Request request) + /// The context for rendering the page. + /// The visual tree control to be processed. + public void Process(IRenderContext renderContext, VisualTreeControl visualTree) { + // test the context + if (renderContext == null) + { + throw new ArgumentNullException(nameof(renderContext), "Parameter cannot be null or empty."); + } + visualTree.Content.Add(new ControlText() { Text = "Hello World" }); } /// - /// Processes the request. + /// Release of unmanaged resources reserved during use. /// - /// The request. - /// The processed response. - public Response Process(Request request) + public void Dispose() { - return null; - } - - /// - /// Redirects to the specified URI. - /// - /// The URI to redirect to. - public void Redirecting(string uri) - { - } } } diff --git a/src/WebExpress.WebUI.Test/TestPlugin.cs b/src/WebExpress.WebUI.Test/TestPlugin.cs index e73e439c..dd582bca 100644 --- a/src/WebExpress.WebUI.Test/TestPlugin.cs +++ b/src/WebExpress.WebUI.Test/TestPlugin.cs @@ -6,18 +6,19 @@ namespace WebExpress.WebUI.Test /// /// A dummy plugin for testing purposes. /// - [Name("webexpress.webui.unittest")] + [Name("TestPlugin")] [Description("plugin.description")] [Icon("/assets/img/Logo.png")] - [Dependency("webexpress.webui")] + [Application()] public sealed class TestPlugin : IPlugin { /// - /// Initialization of the plugin. + /// Initializes a new instance of the class. /// /// The plugin context. - public void Initialization(IPluginContext pluginContext) + private TestPlugin(IPluginContext pluginContext) { + } /// diff --git a/src/WebExpress.WebUI.Test/TestSectionA.cs b/src/WebExpress.WebUI.Test/TestSectionA.cs new file mode 100644 index 00000000..8829608d --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionA.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionA : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionB.cs b/src/WebExpress.WebUI.Test/TestSectionB.cs new file mode 100644 index 00000000..c19681e2 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionB.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionB : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionC.cs b/src/WebExpress.WebUI.Test/TestSectionC.cs new file mode 100644 index 00000000..914219d5 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionC.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionC : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionD.cs b/src/WebExpress.WebUI.Test/TestSectionD.cs new file mode 100644 index 00000000..e1a8e581 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionD.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionD : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionE.cs b/src/WebExpress.WebUI.Test/TestSectionE.cs new file mode 100644 index 00000000..0d412797 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionE.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionE : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionF.cs b/src/WebExpress.WebUI.Test/TestSectionF.cs new file mode 100644 index 00000000..7996eb96 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionF.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionF : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs new file mode 100644 index 00000000..3cf57eb3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs @@ -0,0 +1,77 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the alert control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlAlert : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The log. + /// The test context. + public UnitTestControlAlert(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests the id property of the alert control. + /// + [Theory] + [InlineData(null, @"
              ")] + [InlineData("id", @"
              ")] + [InlineData("03C6031F-04A9-451F-B817-EBD6D32F8B0C", @"
              ")] + public void Id(string id, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAlert(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the alert control. + /// + [Theory] + [InlineData(null, @"
              ")] + public void Text(string text, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAlert() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs new file mode 100644 index 00000000..a8e9638a --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs @@ -0,0 +1,199 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlButton + { + /// + /// Tests the id property of the button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the size property of the button control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the backgroundcolor property of the button control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + public void BackgroundColor(TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the outline property of the button control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + Outline = outline, + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the block property of the button control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButton() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the content property of the button control. + /// + [Fact] + public void Content() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + // test execution + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs new file mode 100644 index 00000000..a7286326 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs @@ -0,0 +1,223 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the buttonlink control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlButtonLink + { + /// + /// Tests the id property of the buttonlink control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the buttonlink control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the buttonlink control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
              b", @"b"" data-bs-toggle=""tooltip"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the size property of the buttonlink control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the backgroundcolor property of the buttonlink control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + public void BackgroundColor(TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the outline property of the buttonlink control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Outline = outline, + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the block property of the buttonlink control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the buttonlink control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlButtonLink() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the content property of the buttonlink control. + /// + [Fact] + public void Content() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlButtonLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlButtonLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlButtonLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + // test execution + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs new file mode 100644 index 00000000..ca4c2bcc --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs @@ -0,0 +1,166 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form control. + /// + public class UnitTestControlForm : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The log. + /// The test context. + public UnitTestControlForm(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm(); + + //var html = control.Render(context); + + //// test execution + //Assert.StartsWith(" + /// Tests a simple form with id. + ///
              + [Fact] + public void EmptyFormWithId() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm("form"); + + //var html = control.Render(context); + + //// test execution + //Assert.StartsWith(@" + /// Tests a simple form. + /// The control elements are added during rendering. + ///
              + [Fact] + public void SimpleFormAtRender() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm(); + //var item = new ControlFormItemInputTextBox() { }; + + //// test execution + //var html = control.Render(context, [item]); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlForm("form", item); + + //// test execution + //var html = control.Render(context); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlForm("form"); + + //control.Add(item); + + //// test execution + //var html = control.Render(context); + //var str = html.ToString(); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a complex form. + /// + [Fact] + public void ComplexForm() + { + //// preconditions + //var expectedResult = Fixture.GetEmbeddedResource("ComplexForm.txt"); + //var context = Fixture.CrerateContext(); + //var item1 = new ControlFormItemInputTextBox() { Label = "Label1", Help = "Help1", Placeholder = "Placeholder1" }; + //var item2 = new ControlFormItemInputTextBox() { Label = "Label2", Help = "Help2", Placeholder = "Placeholder2" }; + //var submitButton = new ControlFormItemButtonSubmit("Submit"); + //var control = new ControlForm("form", item1, item2); + //control.AddPrimaryButton(submitButton); + + + //// test execution + //var html = control.Render(context); + //var str = html.ToString(); + + //// postconditions + //expectedResult = expectedResult.Replace("05c888e8-15f3-4be8-b765-0d7be63cc82b", control.FormId.Id); + //expectedResult = expectedResult.Replace("974c6159-98e3-4ede-8bb5-6bc4d52e1770", control.SubmitType.Id); + + //Assert.Equal(expectedResult.Trim(), str.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs new file mode 100644 index 00000000..5a67cb2a --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs @@ -0,0 +1,140 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the inline form control. + /// + public class UnitTestControlFormInline : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The log. + /// The test context. + public UnitTestControlFormInline(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; + + //var html = control.Render(context); + //var str = html.ToString(); + + //// test execution + //Assert.StartsWith(@" + /// Tests a empty form. + ///
              + [Fact] + public void EmptyFormChangeSubmitText() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; + //control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); + + //var html = control.Render(context); + //var str = html.ToString(); + + //// test execution + //Assert.Contains(@"sendbutton", html.Trim()); + } + + /// + /// Tests a simple form with id. + /// + [Fact] + public void EmptyFormWithId() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; + + //var html = control.Render(context); + + //// test execution + //Assert.StartsWith(@" + /// Tests a simple form. + /// The control elements are added during rendering. + ///
              + [Fact] + public void SimpleFormAtRender() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; + //var item = new ControlFormItemInputTextBox() { }; + + //// test execution + //var html = control.Render(context, [item]); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlForm("form", item) { FormLayout = TypeLayoutForm.Inline }; + + //// test execution + //var html = control.Render(context); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; + + //control.Add(item); + + //// test execution + //var html = control.Render(context); + //var str = html.ToString(); + + //Assert.Contains(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs similarity index 52% rename from src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs rename to src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs index 2b66e790..561f58a5 100644 --- a/src/WebExpress.WebUI.Test/Control/UnitTestControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs @@ -1,8 +1,7 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebControl; using Xunit.Abstractions; -namespace WebExpress.WebUI.Test.Control +namespace WebExpress.WebUI.Test.WebControl { /// /// Tests the inline radio control. @@ -37,13 +36,13 @@ public UnitTestControlFormItemInputRadio(UnitTestControlFixture fixture, ITestOu public void Empty() { // preconditions - var context = Fixture.CrerateContextForm(); - var control = new ControlFormItemInputRadio(); + //var context = Fixture.CrerateContextForm(); + //var control = new ControlFormItemInputRadio(); - var html = control.Render(context).Trim(); + //var html = control.Render(context).Trim(); - // test execution - Assert.StartsWith(@"
              ", html); + //// test execution + //Assert.StartsWith(@"
              ", html); } /// @@ -53,13 +52,13 @@ public void Empty() public void True() { // preconditions - var context = Fixture.CrerateContextForm(); - var control = new ControlFormItemInputRadio() { Checked = true }; + //var context = Fixture.CrerateContextForm(); + //var control = new ControlFormItemInputRadio() { Checked = true }; - var html = control.Render(context).Trim(); + //var html = control.Render(context).Trim(); - // test execution - Assert.StartsWith(@"
              ", html); + //// test execution + //Assert.StartsWith(@"
              ", html); } /// @@ -69,13 +68,13 @@ public void True() public void False() { // preconditions - var context = Fixture.CrerateContextForm(); - var control = new ControlFormItemInputRadio() { Checked = false }; + //var context = Fixture.CrerateContextForm(); + //var control = new ControlFormItemInputRadio() { Checked = false }; - var html = control.Render(context).Trim(); + //var html = control.Render(context).Trim(); - // test execution - Assert.StartsWith(@"
              ", html); + //// test execution + //Assert.StartsWith(@"
              ", html); } /// @@ -84,14 +83,14 @@ public void False() [Fact] public void Description() { - // preconditions - var context = Fixture.CrerateContextForm(); - var control = new ControlFormItemInputRadio() { Description = "abcdefg" }; + //// preconditions + //var context = Fixture.CrerateContextForm(); + //var control = new ControlFormItemInputRadio() { Description = "abcdefg" }; - var html = control.Render(context).Trim(); + //var html = control.Render(context).Trim(); - // test execution - Assert.StartsWith(@"
              ", html); + //// test execution + //Assert.StartsWith(@"
              ", html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs new file mode 100644 index 00000000..08f4f534 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs @@ -0,0 +1,127 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the icon control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlIcon + { + /// + /// Tests the id property of the icon control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlIcon(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the icon control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlIcon() + { + Title = title + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the icon control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlIcon() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the size property of the icon control. + /// + [Theory] + [InlineData(TypeSizeText.Default, @"")] + [InlineData(TypeSizeText.ExtraSmall, @"")] + [InlineData(TypeSizeText.Small, @"")] + [InlineData(TypeSizeText.Large, @"")] + [InlineData(TypeSizeText.ExtraLarge, @"")] + public void Size(TypeSizeText size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlIcon() + { + Size = new PropertySizeText(size) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the vertical alignment property of the icon control. + /// + [Theory] + [InlineData(TypeVerticalAlignment.Default, @"")] + [InlineData(TypeVerticalAlignment.Middle, @"")] + [InlineData(TypeVerticalAlignment.TextTop, @"")] + [InlineData(TypeVerticalAlignment.TextBottom, @"")] + [InlineData(TypeVerticalAlignment.Bottom, @"")] + public void VerticalAlignment(TypeVerticalAlignment verticalAlignment, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlIcon() + { + VerticalAlignment = verticalAlignment + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs new file mode 100644 index 00000000..b8984948 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs @@ -0,0 +1,126 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the image control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlImage + { + /// + /// Tests the id property of the image control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlImage(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the uri property of the image control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlImage() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the width property of the image control. + /// + [Theory] + [InlineData(-1, @"")] + [InlineData(0, @"")] + [InlineData(1, @"")] + public void Width(int width, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlImage() + { + Width = width, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the height property of the image control. + /// + [Theory] + [InlineData(-1, @"")] + [InlineData(0, @"")] + [InlineData(1, @"")] + public void Height(int height, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlImage() + { + Height = height, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the image control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
              b", @"b"" data-toggle=""tooltip"" title=""a
              b"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlImage() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs new file mode 100644 index 00000000..d0cdeed4 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs @@ -0,0 +1,195 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlLink + { + /// + /// Tests the id property of the link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the uri property of the link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the target property of the link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
              b", @"b"" data-bs-toggle=""tooltip"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the link control. + /// + [Fact] + public void Icon() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Icon = new PropertyIcon(TypeIcon.Star) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + + /// + /// Tests the content property of the link control. + /// + [Fact] + public void Content() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + // test execution + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs new file mode 100644 index 00000000..2e5c0311 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs @@ -0,0 +1,90 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the list control. + /// + public class UnitTestControlList : IClassFixture + { + /// + /// Tests the id property of the list control. + /// + [Theory] + [InlineData(null, @"
                ")] + [InlineData("id", @"
                  ")] + [InlineData("03C6031F-04A9-451F-B817-EBD6D32F8B0C", @"
                    ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlList(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the layout property of the list control. + /// + [Theory] + [InlineData(TypeLayoutList.Default, @"
                      ")] + [InlineData(TypeLayoutList.Simple, @"
                        ")] + [InlineData(TypeLayoutList.Group, @"
                          ")] + [InlineData(TypeLayoutList.Horizontal, @"
                            ")] + [InlineData(TypeLayoutList.Flush, @"
                              ")] + public void Layout(TypeLayoutList layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlList() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the add function of the list control. + /// + [Theory] + [MemberData(nameof(GetControlListItemsData))] + public void Add(IEnumerable items, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlList(null, items.ToArray()); + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Provides test data for the Add method of the UnitTestControlList class. + /// + /// An enumerable collection of object arrays, each containing test data. + public static TheoryData, string> GetControlListItemsData() + { + return new TheoryData, string> + { + { new List { new(null, new ControlText() { Text = "Item 1" }) }, @"
                              • Item 1
                              " }, + { new List { new("id") }, @"
                              " }, + { new List { }, "
                                " } + }; + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs new file mode 100644 index 00000000..8ec9efce --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs @@ -0,0 +1,56 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the modal control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlModal + { + /// + /// Tests the id property of the modal control. + /// + [Theory] + [InlineData(null, @"

                                ")] + [InlineData("id", @"

                                ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlModal(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.Trim())); + } + + /// + /// Tests the header property of the modal control. + /// + [Theory] + [InlineData(null, @"

                                ")] + [InlineData("abc", @"

                                abc

                                ")] + + public void Header(string header, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlModal() + { + Header = header + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs new file mode 100644 index 00000000..c660860b --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs @@ -0,0 +1,154 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using Xunit.Abstractions; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the modal form control. + /// + public class UnitTestControlModalForm : IClassFixture + { + /// + /// Returns the log. + /// + protected ITestOutputHelper Output { get; private set; } + + /// + /// Returns the test context. + /// + protected UnitTestControlFixture Fixture { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The log. + /// The test context. + public UnitTestControlModalForm(UnitTestControlFixture fixture, ITestOutputHelper output) + { + Fixture = fixture; + Output = output; + } + + /// + /// Tests a empty form. + /// + [Fact] + public void EmptyForm() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlModalForm(); + + //var html = control.Render(context); + //var str = html.ToString(); + + //// test execution + //Assert.StartsWith(" + /// Tests a simple form with header. + ///
                                + [Fact] + public void EmptyFormWithHeaderAtInstancing() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlModalForm("form", "header"); + + //var html = control.Render(context); + + //// test execution + //Assert.Contains(@"

                                header

                                ", html.Trim()); + } + + /// + /// Tests a simple form with header. + /// + [Fact] + public void EmptyFormWithHeaderAtProperty() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlModalForm("form") { Header = "header" }; + + //var html = control.Render(context); + + //// test execution + //Assert.Contains(@"

                                header

                                ", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added during rendering. + /// + [Fact] + public void SimpleFormAtRender() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var control = new ControlModalForm(); + //var item = new ControlFormItemInputTextBox() { }; + + //// test execution + //var html = control.Render(context, [item]); + ////var str = html.ToString(); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added when instantiating. + /// + [Fact] + public void SimpleFormAtInstancing() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlModalForm("form", item); + + //// test execution + //var html = control.Render(context); + + //Assert.Contains(@"", html.Trim()); + } + + /// + /// Tests a simple form. + /// The control elements are added using add. + /// + [Fact] + public void SimpleFormAtAdd() + { + //// preconditions + //var context = Fixture.CrerateContext(); + //var item = new ControlFormItemInputTextBox() { }; + //var control = new ControlModalForm("form"); + + //control.Add(item); + + //// test execution + //var html = control.Render(context); + + //Assert.Contains(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs new file mode 100644 index 00000000..3c1e1893 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs @@ -0,0 +1,58 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the text control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlText + { + /// + /// Tests the id property of the text control. + /// + [Theory] + [InlineData(null, @"
                                ")] + [InlineData("id", @"
                                ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlText(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the text control. + /// + [Theory] + [InlineData(null, TypeFormatText.Paragraph, @"

                                ")] + [InlineData("abc", TypeFormatText.Paragraph, @"

                                abc

                                ")] + [InlineData("abc", TypeFormatText.Default, @"
                                abc
                                ")] + [InlineData("webexpress.webui:plugin.name", TypeFormatText.H1, @"

                                WebExpress.WebUI

                                ")] + public void Text(string text, TypeFormatText format, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlText() + { + Text = text, + Format = format + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj index a9407b28..c388f9d8 100644 --- a/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj +++ b/src/WebExpress.WebUI.Test/WebExpress.WebUI.Test.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable disable diff --git a/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs b/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs deleted file mode 100644 index 69277ad3..00000000 --- a/src/WebExpress.WebUI.Test/WebFragment/FragmentHeaderPrimary.cs +++ /dev/null @@ -1,27 +0,0 @@ -ο»Ώusing WebExpress.WebApp.WebSection; -using WebExpress.WebCore.WebAttribute; -using WebExpress.WebUI.WebAttribute; -using WebExpress.WebUI.WebControl; -using WebExpress.WebUI.WebFragment; -using static System.Collections.Specialized.BitVector32; - -namespace WebExpress.WebUI.Test.WebFragment -{ - /// - /// A dummy fragment for testing purposes. - /// - [Section(SectionControl.HeaderPrimary)] - [Module] - [Scope] - public sealed class FragmentHeaderPrimary : FragmentControlText - { - /// - /// Initializes a new instance of the class. - /// - public FragmentHeaderPrimary() - { - Text = "FragmentHeaderPrimary"; - Format = TypeFormatText.Paragraph; - } - } -} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs new file mode 100644 index 00000000..1a63ae80 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -0,0 +1,62 @@ +ο»Ώusing WebExpress.WebCore.WebScope; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.Test.WebFragment +{ + /// + /// Test the fragment manager. + /// + [Collection("NonParallelTests")] + public class UnitTestFragmentManager + { + /// + /// Test the id property of the fragment manager. + /// + [Theory] + [InlineData(typeof(TestApplication), typeof(TestFragmentControlText), "webexpress.webui.test.testfragmentcontroltext")] + [InlineData(typeof(TestApplication), typeof(TestFragmentControlList), "webexpress.webui.test.testfragmentcontrollist")] + [InlineData(typeof(TestApplication), typeof(TestFragmentControlLink), "webexpress.webui.test.testfragmentcontrollink")] + public void Id(Type applicationType, Type fragmentType, string id) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault(); + + // test execution + var fragment = componentHub.FragmentManager.GetFragments(application, fragmentType); + + if (id == null) + { + Assert.Empty(fragment); + return; + } + + Assert.Contains(id, fragment.Select(x => x.FragmentId?.ToString())); + } + + /// + /// Test the render function of the fragment manager. + /// + [Theory] + [InlineData(typeof(TestApplication), typeof(TestSectionA), typeof(IScope), @"

                                TestFragmentControlText

                                ")] + [InlineData(typeof(TestApplication), typeof(TestSectionB), typeof(IScope), @"
                                ")] + [InlineData(typeof(TestApplication), typeof(TestSectionC), typeof(IScope), @"TestFragmentControlLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionD), typeof(IScope), @"TestFragmentControlButtonLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionE), typeof(IScope), @"")] + public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault(); + var renderContext = UnitTestControlFixture.CrerateRenderContextMock(application, [scopeType]); + + // test execution + var html = componentHub.FragmentManager.Render(renderContext, sectionType); + + Assert.NotNull(html); + Assert.NotEmpty(html); + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.FirstOrDefault()?.ToString())); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs new file mode 100644 index 00000000..c59818fd --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs @@ -0,0 +1,34 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; + +namespace WebExpress.WebUI.Test.WebPage +{ + /// + /// Test the fragment manager. + /// + [Collection("NonParallelTests")] + public class UnitTestPageManager + { + /// + /// Test the id property of the page manager. + /// + [Theory] + [InlineData(typeof(TestApplication), typeof(TestPage), "webexpress.webui.test.testpage")] + public void Id(Type applicationType, Type pageType, string id) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault(); + + // test execution + var page = componentHub.PageManager.GetPages(pageType, application); + + if (id == null) + { + Assert.Empty(page); + return; + } + + Assert.Contains(id, page.Select(x => x.EndpointId?.ToString())); + } + } +} diff --git a/src/WebExpress.WebUI/Internationalization/de b/src/WebExpress.WebUI/Internationalization/de index 934ee590..db0bb7cd 100644 --- a/src/WebExpress.WebUI/Internationalization/de +++ b/src/WebExpress.WebUI/Internationalization/de @@ -2,18 +2,6 @@ plugin.name=WebExpress.WebUI plugin.description=Stellt Basiskomponenten bereit. -module.name=WebExpress.WebUI -module.description=Stellt Basiskomponenten bereit. - -fragmentmanager.initialization=Der Fragmentmanager wurde initialisiert. -fragmentmanager.register=Das Fragment '{0}' wurde in der Sektion '{1}' der Anwendung '{2}' registriert. -fragmentmanager.error.section=Die Angabe der Sektion ist fehlerhaft. -fragmentmanager.wrongtype=Der Typ '{0}' implementiert die Schnittstelle '{1}' nicht. -fragmentmanager.moduleless=Das Fragment '{0}' aus dem Plugin '{1}' besitzt keine Angaben zum Modul. -fragmentmanager.addfragment.duplicate=Das Fragment '{0}' des Moduls '{1}' ist bereits hinzugefΓΌgt worden. -fragmentmanager.titel=Fragmente: -fragmentmanager.fragment={0} - form.empty.id=Das Formular verfΓΌgt ΓΌber keine Id! form.submit.label=Speichern form.next.label=Speichern und weiter diff --git a/src/WebExpress.WebUI/Internationalization/en b/src/WebExpress.WebUI/Internationalization/en index 03a30a76..92a39548 100644 --- a/src/WebExpress.WebUI/Internationalization/en +++ b/src/WebExpress.WebUI/Internationalization/en @@ -2,18 +2,6 @@ plugin.name=WebExpress.WebUI plugin.description=Provides basic components. -module.name=WebExpress.WebUI -module.description=Provides basic components. - -fragmentmanager.initialization=The fragment manager has been initialized. -fragmentmanager.register=The fragment '{0}' has been registered in the '{1}' section of application '{2}'. -fragmentmanager.error.section=The section is incorrect. -fragmentmanager.wrongtype=The type '{0}' does not implement the interface '{1}'. -fragmentmanager.moduleless=The fragment '{0}' from the plugin '{1}' has no information about the module. -fragmentmanager.addfragment.duplicate=The fragment '{0}' of module '{1}' has already been added. -fragmentmanager.titel=Fragments: -fragmentmanager.fragment={0} - form.empty.id=The form does not have an id! form.submit.label=Submit form.next.label=Next diff --git a/src/WebExpress.WebUI/WebAttribute/IComponentAttribute.cs b/src/WebExpress.WebUI/WebAttribute/IComponentAttribute.cs deleted file mode 100644 index d324ccdd..00000000 --- a/src/WebExpress.WebUI/WebAttribute/IComponentAttribute.cs +++ /dev/null @@ -1,9 +0,0 @@ -ο»Ώnamespace WebExpress.WebUI.WebAttribute -{ - /// - /// Kennzeichnet eine Klasse als Plugin-Komponente - /// - public interface IFragmentAttribute - { - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs b/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs deleted file mode 100644 index c5e0738f..00000000 --- a/src/WebExpress.WebUI/WebAttribute/OrderAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -ο»Ώnamespace WebExpress.WebUI.WebAttribute -{ - /// - /// Attribute used to identify a class as a plugin component. - /// - public class OrderAttribute : System.Attribute, IFragmentAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The order within the section. - public OrderAttribute(int order) - { - } - - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs deleted file mode 100644 index 6a41cd8f..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SectionAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -ο»Ώnamespace WebExpress.WebUI.WebAttribute -{ - /// - /// Attribute to identify a section. - /// - public class SectionAttribute : System.Attribute, IFragmentAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The section where the component is embedded. - public SectionAttribute(string section) - { - } - - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs deleted file mode 100644 index 278a10b8..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingContextAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebAttribute; - -namespace WebExpress.WebUI.WebAttribute -{ - /// - /// Attribute to specify the context in which the settings page is associated. - /// - [AttributeUsage(AttributeTargets.Class)] - public class SettingContextAttribute : Attribute, IEndpointAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The context in which the settings page is associated. - public SettingContextAttribute(string context) - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs deleted file mode 100644 index b7e3becd..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingGroupAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebAttribute; - -namespace WebExpress.WebUI.WebAttribute -{ - /// - /// Attribute to define a setting group for identity. - /// - [AttributeUsage(AttributeTargets.Class)] - public class SettingGroupAttribute : System.Attribute, IEndpointAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The group name. - public SettingGroupAttribute(string name) - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs deleted file mode 100644 index c74e28ea..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingHideAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; - -namespace WebExpress.WebUI.WebAttribute -{ - /// - /// Represents an attribute that hides a setting in the web UI. - /// - public class SettingHideAttribute : System.Attribute, IEndpointAttribute - { - /// - /// Initializes a new instance of the class. - /// - public SettingHideAttribute() - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs b/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs deleted file mode 100644 index ebc874fe..00000000 --- a/src/WebExpress.WebUI/WebAttribute/SettingIconAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebAttribute; -using WebExpress.WebUI.WebControl; - -namespace WebExpress.WebUI.WebAttribute -{ - /// - /// Attribute to set an icon for a setting. - /// - public class SettingIconAttribute : System.Attribute, IEndpointAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The icon. - public SettingIconAttribute(TypeIcon icon) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The icon. - public SettingIconAttribute(string icon) - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs b/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs new file mode 100644 index 00000000..1ea848b2 --- /dev/null +++ b/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs @@ -0,0 +1,25 @@ +ο»Ώusing WebExpress.WebCore; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebComponent; + +namespace WebExpress.WebUI.WebComponent +{ + /// + /// Represents the UI component hub that inherits from . + /// + public class ComponentHubUI : ComponentHub, IComponentHubUI + { + /// + /// Initializes a new instance of the class. + /// + /// The HTTP server context. + protected ComponentHubUI(IHttpServerContext httpServerContext) + : base(httpServerContext) + { + if (InternationalizationManager is InternationalizationManager internationalizationManager) + { + internationalizationManager.Register(typeof(ComponentHubUI).Assembly, typeof(ComponentHubUI).Assembly.GetName().Name?.ToLower()); + } + } + } +} diff --git a/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs b/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs new file mode 100644 index 00000000..2789aba6 --- /dev/null +++ b/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebComponent; + +namespace WebExpress.WebUI.WebComponent +{ + /// + /// Interface for WebExpress.WebUI of the component hub. + /// + public interface IComponentHubUI : IComponentHub + { + } +} diff --git a/src/WebExpress.WebUI/WebControl/Control.cs b/src/WebExpress.WebUI/WebControl/Control.cs index e3093345..a62d2ad6 100644 --- a/src/WebExpress.WebUI/WebControl/Control.cs +++ b/src/WebExpress.WebUI/WebControl/Control.cs @@ -3,10 +3,13 @@ using System.Linq; using System.Runtime.CompilerServices; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Abstract base class for all controls. + /// public abstract class Control : IControl { /// @@ -107,17 +110,17 @@ public virtual TypeHeight Height /// /// Returns or sets the css class. /// - public List Classes { get; set; } = new List(); + public List Classes { get; set; } = []; /// /// Retruns or sets properties determined by enums. /// - protected Dictionary, Func>> Propertys { get; private set; } = new Dictionary, Func>>(); + protected Dictionary, Func>> Propertys { get; private set; } = []; /// /// Returns or sets the css style. /// - public List Styles { get; set; } = new List(); + public List Styles { get; set; } = []; /// /// Returns or sets the role. @@ -134,17 +137,10 @@ public virtual TypeHeight Height /// public bool Enable { get; set; } = true; - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public abstract IHtmlNode Render(RenderContext context); - /// /// Initializes a new instance of the class. /// - /// The id. + /// The control id. public Control(string id = null) { Id = id; @@ -193,7 +189,7 @@ protected Enum GetProperty([CallerMemberName] string propertyName = "") /// /// Returns a property. /// - /// he name of the property. + /// The name of the property. /// The value. protected IProperty GetPropertyObject([CallerMemberName] string propertyName = "") { @@ -299,5 +295,12 @@ protected string GetStyles() return string.Join(" ", Styles.Union(list)); } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public abstract IHtmlNode Render(IRenderControlContext context); } } diff --git a/src/WebExpress.WebUI/WebControl/ControlArlert.cs b/src/WebExpress.WebUI/WebControl/ControlArlert.cs index 161bf7d2..a233ad7f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlArlert.cs +++ b/src/WebExpress.WebUI/WebControl/ControlArlert.cs @@ -1,5 +1,5 @@ ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -55,11 +55,11 @@ public ControlAlert(string id = null) } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) { var head = new HtmlElementTextSemanticsStrong ( diff --git a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs index 3fe0b0c1..bd8f16c6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs @@ -1,93 +1,93 @@ -ο»Ώusing System; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Display of a name-value pair. - /// - public class ControlAttribute : Control - { - /// - /// Returns or sets the text.farbe des Namens - /// - public PropertyColorText NameColor { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Display of a name-value pair. +// /// +// public class ControlAttribute : Control +// { +// /// +// /// Returns or sets the text.farbe des Namens +// /// +// public PropertyColorText NameColor { get; set; } - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } - /// - /// Returns or sets the name. - /// - public string Name { get; set; } +// /// +// /// Returns or sets the name. +// /// +// public string Name { get; set; } - /// - /// Returns or sets the value. - /// - public string Value { get; set; } +// /// +// /// Returns or sets the value. +// /// +// public string Value { get; set; } - /// - /// Returns or sets a link. - /// - public Uri Uri { get; set; } +// /// +// /// Returns or sets a link. +// /// +// public Uri Uri { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlAttribute(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlAttribute(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - if (!Enable) - { - return null; - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// if (!Enable) +// { +// return null; +// } - var icon = new HtmlElementTextSemanticsSpan() - { - Class = Icon?.ToClass() - }; +// var icon = new HtmlElementTextSemanticsSpan() +// { +// Class = Icon?.ToClass() +// }; - var name = new HtmlElementTextSemanticsSpan(new HtmlText(context.I18N(Name))) - { - Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", - Class = NameColor?.ToClass() - }; +// var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Name))) +// { +// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", +// Class = NameColor?.ToClass() +// }; - var value = new HtmlElementTextSemanticsSpan(new HtmlText(context.I18N(Value))) - { - Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_value", - Class = NameColor?.ToClass() - }; +// var value = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Value))) +// { +// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_value", +// Class = NameColor?.ToClass() +// }; - var html = new HtmlElementTextContentDiv - ( - Icon != null && Icon.HasIcon ? icon : null, - name, - Uri != null ? new HtmlElementTextSemanticsA(value) { Href = Uri.ToString() } : value - ) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; +// var html = new HtmlElementTextContentDiv +// ( +// Icon != null && Icon.HasIcon ? icon : null, +// name, +// Uri != null ? new HtmlElementTextSemanticsA(value) { Href = Uri.ToString() } : value +// ) +// { +// Id = Id, +// Class = GetClasses(), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs index 51725771..4f933552 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs @@ -1,95 +1,95 @@ -ο»Ώusing System; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlAvatar : Control - { - /// - /// Returns or sets the avatar image. - /// - public Uri Image { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlAvatar : Control +// { +// /// +// /// Returns or sets the avatar image. +// /// +// public Uri Image { get; set; } - /// - /// Returns or sets the name of the user. - /// - public string User { get; set; } +// /// +// /// Returns or sets the name of the user. +// /// +// public string User { get; set; } - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeButton Size +// { +// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets a modal dialogue. - /// - public ControlModal Modal { get; set; } +// /// +// /// Returns or sets a modal dialogue. +// /// +// public ControlModal Modal { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlAvatar(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlAvatar(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var img = default(HtmlElement); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var img = default(HtmlElement); - if (Image != null) - { - img = new HtmlElementMultimediaImg() { Src = Image.ToString(), Class = "" }; - } - else if (!string.IsNullOrWhiteSpace(User)) - { - var split = User.Split(' '); - var i = split[0].FirstOrDefault().ToString(); - i += split.Count() > 1 ? split[1].FirstOrDefault().ToString() : ""; +// if (Image != null) +// { +// img = new HtmlElementMultimediaImg() { Src = Image.ToString(), Class = "" }; +// } +// else if (!string.IsNullOrWhiteSpace(User)) +// { +// var split = User.Split(' '); +// var i = split[0].FirstOrDefault().ToString(); +// i += split.Count() > 1 ? split[1].FirstOrDefault().ToString() : ""; - img = new HtmlElementTextSemanticsB(new HtmlText(i)) - { - Class = "bg-info text-light" - }; - } +// img = new HtmlElementTextSemanticsB(new HtmlText(i)) +// { +// Class = "bg-info text-light" +// }; +// } - var html = new HtmlElementTextContentDiv(img, new HtmlText(User)) - { - Id = Id, - Class = Css.Concatenate("profile", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// var html = new HtmlElementTextContentDiv(img, new HtmlText(User)) +// { +// Id = Id, +// Class = Css.Concatenate("profile", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - if (Modal != null) - { - html.AddUserAttribute("data-bs-toggle", "modal"); - html.AddUserAttribute("data-bs-target", "#" + Modal.Id); +// if (Modal != null) +// { +// html.AddUserAttribute("data-bs-toggle", "modal"); +// html.AddUserAttribute("data-bs-target", "#" + Modal.Id); - return new HtmlList(html, Modal.Render(context)); - } +// return new HtmlList(html, Modal.Render(context)); +// } - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlBadge.cs b/src/WebExpress.WebUI/WebControl/ControlBadge.cs index f4c0be55..14cace34 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBadge.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBadge.cs @@ -1,129 +1,129 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// A numerical indicator. - /// - public class ControlBadge : Control - { - /// - /// Returns or set the background color. - /// - public new PropertyColorBackgroundBadge BackgroundColor - { - get => (PropertyColorBackgroundBadge)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); - } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// A numerical indicator. +// /// +// public class ControlBadge : Control +// { +// /// +// /// Returns or set the background color. +// /// +// public new PropertyColorBackgroundBadge BackgroundColor +// { +// get => (PropertyColorBackgroundBadge)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); +// } - /// - /// Return or specifies whether rounded corners should be used. - /// - public TypePillBadge Pill - { - get => (TypePillBadge)GetProperty(TypePillBadge.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Return or specifies whether rounded corners should be used. +// /// +// public TypePillBadge Pill +// { +// get => (TypePillBadge)GetProperty(TypePillBadge.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the target uri. - /// - public Uri Uri { get; set; } +// /// +// /// Returns or sets the target uri. +// /// +// public Uri Uri { get; set; } - /// - /// Returns or sets the value. - /// - public string Value { get; set; } +// /// +// /// Returns or sets the value. +// /// +// public string Value { get; set; } - /// - /// Return or specifies the vertical orientation.. - /// - public TypeVerticalAlignment VerticalAlignment - { - get => (TypeVerticalAlignment)GetProperty(TypeVerticalAlignment.Default); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Return or specifies the vertical orientation.. +// /// +// public TypeVerticalAlignment VerticalAlignment +// { +// get => (TypeVerticalAlignment)GetProperty(TypeVerticalAlignment.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the size. - /// - public PropertySizeText Size - { - get => (PropertySizeText)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); - } +// /// +// /// Returns or sets the size. +// /// +// public PropertySizeText Size +// { +// get => (PropertySizeText)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlBadge(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlBadge(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The value. - public ControlBadge(string id, string value) - : base(id) - { - Value = value; +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The value. +// public ControlBadge(string id, string value) +// : base(id) +// { +// Value = value; - Init(); - } +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The value. - public ControlBadge(string id, int value) - : base(id) - { - Value = value.ToString(); +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The value. +// public ControlBadge(string id, int value) +// : base(id) +// { +// Value = value.ToString(); - Init(); - } +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - if (Uri != null) - { - return new HtmlElementTextSemanticsA(new HtmlText(Value.ToString())) - { - Id = Id, - Class = Css.Concatenate("badge", GetClasses()), - Style = GetStyles(), - Href = Uri.ToString(), - Role = Role - }; - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// if (Uri != null) +// { +// return new HtmlElementTextSemanticsA(new HtmlText(Value.ToString())) +// { +// Id = Id, +// Class = Css.Concatenate("badge", GetClasses()), +// Style = GetStyles(), +// Href = Uri.ToString(), +// Role = Role +// }; +// } - return new HtmlElementTextSemanticsSpan(new HtmlText(Value.ToString())) - { - Id = Id, - Class = Css.Concatenate("badge", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// return new HtmlElementTextSemanticsSpan(new HtmlText(Value.ToString())) +// { +// Id = Id, +// Class = Css.Concatenate("badge", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs index 828f8150..68810bb3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs @@ -1,162 +1,162 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlBreadcrumb : Control - { - /// - /// Return or sets the uri. - /// - public string Uri { get; set; } - - /// - /// Return or sets the root element. - /// - public string EmptyName { get; set; } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Return or sets a prefix, which is statically displayed in front of the links. - /// - public string Prefix { get; set; } - - /// - /// Return or sets how many links to display. It will be truncated at the beginning of the link chain. - /// - public ushort TakeLast { get; set; } = ushort.MaxValue; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlBreadcrumb(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// Der Verzeichnispfad - public ControlBreadcrumb(string id, string uri) - : base(id) - { - Uri = uri; - } - - /// - /// Initialization - /// - private void Init() - { - Size = TypeSizeButton.Small; - BackgroundColor = new PropertyColorBackground(TypeColorBackground.Light); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentOl() - { - Class = Css.Concatenate("breadcrumb bg-light ps-2", GetClasses()), - Style = GetStyles(), - }; - - if (!string.IsNullOrWhiteSpace(Prefix)) - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new HtmlElementTextContentDiv - ( - new HtmlText(InternationalizationManager.I18N(context.Culture, Prefix)) - ) - { - Class = "me-2 text-muted" - } - ) - ); - } - - foreach (var part in context.Uri.PathSegments) - { - if (part.Display != null) - { - var display = part.GetDisplay(context.Culture); - var href = part.ToString(); - - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - //new ControlIcon(Page) - //{ - // Icon = path.Icon - //}.ToHtml(), - new HtmlElementTextSemanticsA(display) - { - Href = href - } - ) - { - Class = "breadcrumb-item" - } - ); - } - } - - //var takeLast = Math.Min(TakeLast, resourceUri.Path.Count); - //var from = resourceUri.Path.Count - takeLast; - - //for (int i = from + 1; i < resourceUri.Path.Count + 1; i++) - //{ - // var path = resourceUri.Take(i); - - // if (path.Display != null) - // { - // var display = I18N(context.Culture, path.Display); - // var href = path.ToString(); - - // html.Elements.Add - // ( - // new HtmlElementTextContentLi - // ( - // //new ControlIcon(Page) - // //{ - // // Icon = path.Icon - // //}.ToHtml(), - // new HtmlElementTextSemanticsA(display) - // { - // Href = href, - // Class = "link" - // } - // ) - // { - // Class = "breadcrumb-item" - // } - // ); - // } - //} - //} - - return html; - } - } -} +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlBreadcrumb : Control +// { +// /// +// /// Return or sets the uri. +// /// +// public string Uri { get; set; } + +// /// +// /// Return or sets the root element. +// /// +// public string EmptyName { get; set; } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeButton Size +// { +// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Return or sets a prefix, which is statically displayed in front of the links. +// /// +// public string Prefix { get; set; } + +// /// +// /// Return or sets how many links to display. It will be truncated at the beginning of the link chain. +// /// +// public ushort TakeLast { get; set; } = ushort.MaxValue; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlBreadcrumb(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// Der Verzeichnispfad +// public ControlBreadcrumb(string id, string uri) +// : base(id) +// { +// Uri = uri; +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Size = TypeSizeButton.Small; +// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Light); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentOl() +// { +// Class = Css.Concatenate("breadcrumb bg-light ps-2", GetClasses()), +// Style = GetStyles(), +// }; + +// if (!string.IsNullOrWhiteSpace(Prefix)) +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new HtmlElementTextContentDiv +// ( +// new HtmlText(I18N.Translate(context.Culture, Prefix)) +// ) +// { +// Class = "me-2 text-muted" +// } +// ) +// ); +// } + +// foreach (var part in context.Uri.PathSegments) +// { +// if (part.Display != null) +// { +// var display = part.GetDisplay(context.Culture); +// var href = part.ToString(); + +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// //new ControlIcon(Page) +// //{ +// // Icon = path.Icon +// //}.ToHtml(), +// new HtmlElementTextSemanticsA(display) +// { +// Href = href +// } +// ) +// { +// Class = "breadcrumb-item" +// } +// ); +// } +// } + +// //var takeLast = Math.Min(TakeLast, resourceUri.Path.Count); +// //var from = resourceUri.Path.Count - takeLast; + +// //for (int i = from + 1; i < resourceUri.Path.Count + 1; i++) +// //{ +// // var path = resourceUri.Take(i); + +// // if (path.Display != null) +// // { +// // var display = I18N(context.Culture, path.Display); +// // var href = path.ToString(); + +// // html.Elements.Add +// // ( +// // new HtmlElementTextContentLi +// // ( +// // //new ControlIcon(Page) +// // //{ +// // // Icon = path.Icon +// // //}.ToHtml(), +// // new HtmlElementTextSemanticsA(display) +// // { +// // Href = href, +// // Class = "link" +// // } +// // ) +// // { +// // Class = "breadcrumb-item" +// // } +// // ); +// // } +// //} +// //} + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index 3cb4a024..b21dc4e5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -2,10 +2,13 @@ using System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a button control. + /// public class ControlButton : Control, IControlButton { /// @@ -41,9 +44,9 @@ public TypeBlockButton Block } /// - /// Returns or sets the content. + /// Returns the content. /// - public List Content { get; private set; } + public IEnumerable Content { get; private set; } = []; /// /// Returns or sets the text. @@ -78,30 +81,24 @@ public TypeActive Active /// Initializes a new instance of the class. /// /// The id of the control. - public ControlButton(string id = null) + /// The child controls to be added to the button. + public ControlButton(string id = null, params Control[] content) : base(id) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() { Size = TypeSizeButton.Default; - Content = new List(); + Content = content ?? []; } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) { var html = new HtmlElementFieldButton() { + Id = Id, Type = "button", Value = Value, Class = Css.Concatenate("btn", GetClasses()), @@ -128,7 +125,7 @@ public override IHtmlNode Render(RenderContext context) if (!string.IsNullOrWhiteSpace(Text)) { - html.Elements.Add(new HtmlText(InternationalizationManager.I18N(context.Culture, Text))); + html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); } if (!string.IsNullOrWhiteSpace(OnClick?.ToString())) @@ -136,7 +133,7 @@ public override IHtmlNode Render(RenderContext context) html.AddUserAttribute("onclick", OnClick?.ToString()); } - if (Content.Count > 0) + if (Content.Any()) { html.Elements.AddRange(Content.Select(x => x.Render(context))); } @@ -147,11 +144,11 @@ public override IHtmlNode Render(RenderContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.WebUI.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.WebUI.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } else if (Modal.Type == TypeModal.Modal) { diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index ca4e155c..df96948f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -1,10 +1,13 @@ ο»Ώusing System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a link button control. + /// public class ControlButtonLink : ControlButton { /// @@ -15,44 +18,36 @@ public class ControlButtonLink : ControlButton /// /// Returns or sets the tooltip. /// - public string Title { get; set; } + public string Tooltip { get; set; } /// /// Initializes a new instance of the class. /// /// The id of the control. - public ControlButtonLink(string id = null) - : base(id) + /// The child controls to be added to the button. + public ControlButtonLink(string id = null, params Control[] content) + : base(id, content) { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Size = TypeSizeButton.Default; Classes.Add("btn"); } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) { - var text = context.I18N(Text); + var text = I18N.Translate(Text); var html = new HtmlElementTextSemanticsA() { Id = Id, - Class = Css.Concatenate(GetClasses(), Size.ToClass()), + Class = GetClasses(), Style = GetStyles(), Role = Role, Href = Uri?.ToString(), - Title = Title, + Title = Tooltip, OnClick = OnClick?.ToString() }; @@ -77,7 +72,7 @@ public override IHtmlNode Render(RenderContext context) html.Elements.Add(new HtmlText(text)); } - if (Content.Count > 0) + if (Content.Any()) { html.Elements.AddRange(Content.Select(x => x.Render(context))); } @@ -88,12 +83,12 @@ public override IHtmlNode Render(RenderContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Modal) @@ -104,6 +99,11 @@ public override IHtmlNode Render(RenderContext context) return new HtmlList(html, Modal.Modal.Render(context)); } + if (!string.IsNullOrWhiteSpace(Tooltip)) + { + html.AddUserAttribute("data-bs-toggle", "tooltip"); + } + return html; } } diff --git a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs index 9db1cd0e..2102d5f4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs @@ -1,91 +1,91 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlCanvas : Control - { - /// - /// Returns or sets the content. - /// - public List Content { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlCanvas : Control +// { +// /// +// /// Returns or sets the content. +// /// +// public List Content { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlCanvas(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlCanvas(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlCanvas(params Control[] content) - : this() - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlCanvas(params Control[] content) +// : this() +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlCanvas(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlCanvas(string id, params Control[] content) +// : this(id) +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlCanvas(string id, IEnumerable content) - : this(id) - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlCanvas(string id, IEnumerable content) +// : this(id) +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlCanvas(string id, List content) - : base(id) - { - Content = content; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlCanvas(string id, List content) +// : base(id) +// { +// Content = content; +// } - /// - /// Initialization - /// - private void Init() - { - Content = new List(); - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// Content = new List(); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementScriptingCanvas() - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementScriptingCanvas() +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs index 7329ec96..cb91db2d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs @@ -1,99 +1,99 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// InformationszΓ€hler - /// - public class ControlCardCounter : ControlPanelCard - { - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// InformationszΓ€hler +// /// +// public class ControlCardCounter : ControlPanelCard +// { +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } - /// - /// Returns or sets the value. des Counters - /// - public string Value { get; set; } +// /// +// /// Returns or sets the value. des Counters +// /// +// public string Value { get; set; } - /// - /// Returns or sets the value of the progrss. - /// - public int Progress { get; set; } +// /// +// /// Returns or sets the value of the progrss. +// /// +// public int Progress { get; set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlCardCounter(string id = null) - : base(id) - { - TextColor = new PropertyColorText(TypeColorText.Default); - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlCardCounter(string id = null) +// : base(id) +// { +// TextColor = new PropertyColorText(TypeColorText.Default); +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - Progress = -1; - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// Progress = -1; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Content.Clear(); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Content.Clear(); - if (Icon != null && Icon.HasIcon) - { - Content.Add(new ControlIcon() - { - Icon = Icon, - TextColor = TextColor, - HorizontalAlignment = TypeHorizontalAlignment.Right - }); - } +// if (Icon != null && Icon.HasIcon) +// { +// Content.Add(new ControlIcon() +// { +// Icon = Icon, +// TextColor = TextColor, +// HorizontalAlignment = TypeHorizontalAlignment.Right +// }); +// } - var text = new ControlText(string.IsNullOrWhiteSpace(Id) ? null : Id + "_header") - { - Text = Value, - Format = TypeFormatText.H4 - }; +// var text = new ControlText(string.IsNullOrWhiteSpace(Id) ? null : Id + "_header") +// { +// Text = Value, +// Format = TypeFormatText.H4 +// }; - var info = new ControlText() - { - Text = Text, - Format = TypeFormatText.Span, - TextColor = new PropertyColorText(TypeColorText.Muted) - }; +// var info = new ControlText() +// { +// Text = Text, +// Format = TypeFormatText.Span, +// TextColor = new PropertyColorText(TypeColorText.Muted) +// }; - Content.Add(new ControlPanel(text, info) { }); +// Content.Add(new ControlPanel(text, info) { }); - if (Progress > -1) - { - Content.Add(new ControlProgressBar() - { - Value = Progress, - Format = TypeFormatProgress.Striped, - BackgroundColor = BackgroundColor, - //Color = Color, - Size = TypeSizeProgress.Small - }); - } +// if (Progress > -1) +// { +// Content.Add(new ControlProgressBar() +// { +// Value = Progress, +// Format = TypeFormatProgress.Striped, +// BackgroundColor = BackgroundColor, +// //Color = Color, +// Size = TypeSizeProgress.Small +// }); +// } - return base.Render(context); - } - } -} +// return base.Render(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs index 13306a39..f7d8daf2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs @@ -1,115 +1,115 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Creates a slideshow. - /// - public class ControlCarousel : Control - { - /// - /// Returns or sets the content. - /// - public List Items { get; private set; } = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlCarousel(string id = null) - : base(string.IsNullOrWhiteSpace(id) ? "carousel" : id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The contents of the slideshow. - public ControlCarousel(params ControlCarouselItem[] items) - : this() - { - Items.AddRange(items); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - // indicators - var indicators = new HtmlElementTextContentUl() { Class = "carousel-indicators" }; - var index = 0; - - foreach (var v in Items) - { - var i = new HtmlElementTextContentLi() { Class = index == 0 ? "active" : string.Empty }; - i.AddUserAttribute("data-bs-target", "#" + Id); - i.AddUserAttribute("data-bs-slide-to", index.ToString()); - - indicators.Elements.Add(i); - - index++; - } - - index = 0; - - // items - var inner = new HtmlElementTextContentDiv() { Class = "carousel-inner" }; - foreach (var v in Items) - { - var i = new HtmlElementTextContentDiv(v?.Control.Render(context)) { Class = index == 0 ? "carousel-item active" : "carousel-item" }; - - if (!string.IsNullOrWhiteSpace(v.Headline) || !string.IsNullOrWhiteSpace(v.Text)) - { - var caption = new HtmlElementTextContentDiv - ( - new HtmlElementSectionH3() { Text = v.Headline }, - new HtmlElementTextContentP() { Text = v.Text } - ) - { - Class = "carousel-caption" - }; - - i.Elements.Add(caption); - } - - inner.Elements.Add(i); - - index++; - } - - // navigation - var navLeft = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-prev-icon" }) - { - Class = "carousel-control-prev", - Href = "#" + Id - }; - navLeft.AddUserAttribute("data-bs-slide", "prev"); - - var navRight = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-next-icon" }) - { - Class = "carousel-control-next", - Href = "#" + Id - }; - navRight.AddUserAttribute("data-bs-slide", "next"); - - var html = new HtmlElementTextContentDiv - ( - indicators, inner, navLeft, navRight - ) - { - Id = Id, - Class = Css.Concatenate("carousel slide", GetClasses()), - Style = GetStyles() - }; - - html.AddUserAttribute("data-bs-ride", "carousel"); - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Creates a slideshow. +// /// +// public class ControlCarousel : Control +// { +// /// +// /// Returns or sets the content. +// /// +// public List Items { get; private set; } = new List(); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlCarousel(string id = null) +// : base(string.IsNullOrWhiteSpace(id) ? "carousel" : id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The contents of the slideshow. +// public ControlCarousel(params ControlCarouselItem[] items) +// : this() +// { +// Items.AddRange(items); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// // indicators +// var indicators = new HtmlElementTextContentUl() { Class = "carousel-indicators" }; +// var index = 0; + +// foreach (var v in Items) +// { +// var i = new HtmlElementTextContentLi() { Class = index == 0 ? "active" : string.Empty }; +// i.AddUserAttribute("data-bs-target", "#" + Id); +// i.AddUserAttribute("data-bs-slide-to", index.ToString()); + +// indicators.Elements.Add(i); + +// index++; +// } + +// index = 0; + +// // items +// var inner = new HtmlElementTextContentDiv() { Class = "carousel-inner" }; +// foreach (var v in Items) +// { +// var i = new HtmlElementTextContentDiv(v?.Control.Render(context)) { Class = index == 0 ? "carousel-item active" : "carousel-item" }; + +// if (!string.IsNullOrWhiteSpace(v.Headline) || !string.IsNullOrWhiteSpace(v.Text)) +// { +// var caption = new HtmlElementTextContentDiv +// ( +// new HtmlElementSectionH3() { Text = v.Headline }, +// new HtmlElementTextContentP() { Text = v.Text } +// ) +// { +// Class = "carousel-caption" +// }; + +// i.Elements.Add(caption); +// } + +// inner.Elements.Add(i); + +// index++; +// } + +// // navigation +// var navLeft = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-prev-icon" }) +// { +// Class = "carousel-control-prev", +// Href = "#" + Id +// }; +// navLeft.AddUserAttribute("data-bs-slide", "prev"); + +// var navRight = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-next-icon" }) +// { +// Class = "carousel-control-next", +// Href = "#" + Id +// }; +// navRight.AddUserAttribute("data-bs-slide", "next"); + +// var html = new HtmlElementTextContentDiv +// ( +// indicators, inner, navLeft, navRight +// ) +// { +// Id = Id, +// Class = Css.Concatenate("carousel slide", GetClasses()), +// Style = GetStyles() +// }; + +// html.AddUserAttribute("data-bs-ride", "carousel"); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs index d04fad99..8f50f631 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs @@ -1,31 +1,31 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - /// - /// Creates a slideshow element. - /// - public class ControlCarouselItem - { - /// - /// Returns or sets the headline. - /// - public string Headline { get; set; } +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Creates a slideshow element. +// /// +// public class ControlCarouselItem +// { +// /// +// /// Returns or sets the headline. +// /// +// public string Headline { get; set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Retruns or sets the slideshow element, such as an image. - /// - public IControl Control { get; set; } +// /// +// /// Retruns or sets the slideshow element, such as an image. +// /// +// public IControl Control { get; set; } - /// - /// Initializes a new instance of the class. - /// - public ControlCarouselItem() - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// public ControlCarouselItem() +// { +// } - } -} +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlChart.cs b/src/WebExpress.WebUI/WebControl/ControlChart.cs index 60d1db3d..fcb1159c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChart.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChart.cs @@ -1,170 +1,165 @@ -ο»Ώusing System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebUri; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlChart : Control - { - /// - /// Returns or sets the type. - /// - public TypeChart Type { get; set; } - - /// - /// Returns or sets the title. - /// - public string Title { get; set; } - - /// - /// Returns or sets the title of the x-axis. - /// - public string TitleX { get; set; } - - /// - /// Returns or sets the title of the y-axis. - /// - public string TitleY { get; set; } - - /// - /// Returns or sets the data. - /// - public ICollection Labels { get; set; } = new List(); - - /// - /// Returns or sets the width. - /// - public new int Width { get; set; } - - /// - /// Returns or sets the height. - /// - public new int Height { get; set; } - - /// - /// Returns or sets the minimum. - /// - public float Minimum { get; set; } = float.MinValue; - - /// - /// Returns or sets the maximum. - /// - public float Maximum { get; set; } = float.MaxValue; - - /// - /// Returns or sets the data. - /// - public ICollection Data { get; set; } = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlChart(string id = null) - : base(id) - { - } - - /// - /// Initializes the control. - /// - /// The context in which the control is rendered. - public void Initialize(RenderContext context) - { - var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module)); - if (module != null) - { - context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(module.ContextPath, "/assets/js/Chart.min.js")); - context.VisualTree.CssLinks.Add(UriResource.Combine(module.ContextPath, "/assets/css/Chart.min.css")); - } - - var builder = new StringBuilder(); - var data = new List(); - builder.Append($"var config_{Id} = {{"); - //if (Type != TypeChart.Polar) - { - builder.Append($"type:'{Type.ToType()}',"); - } - builder.Append("data:{"); - builder.Append($"labels:[{string.Join(",", Labels.Select(x => $"'{x}'"))}],"); - builder.Append("datasets:[{"); - foreach (var v in Data) - { - var buf = new StringBuilder(); - - buf.Append($"label:'{v.Title}',"); - buf.Append($"backgroundColor:{(v.BackgroundColor.Count <= 1 ? v.BackgroundColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BackgroundColor.Select(x => $"'{x}'"))} ]")},"); - buf.Append($"borderColor:{(v.BorderColor.Count <= 1 ? v.BorderColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BorderColor.Select(x => $"'{x}'"))} ]")},"); - buf.Append($"data:["); - if (v.Data != null) - { - buf.Append(string.Join(",", v.Data.Select(x => x.ToString(CultureInfo.InvariantCulture)))); - } - buf.Append($"],"); - if (Type == TypeChart.Line) - { - buf.Append($"fill:'{v.Fill.ToType()}',"); - buf.Append($"pointStyle:'{v.Point.ToType()}'"); - } - data.Add(buf); - } - builder.Append(string.Join("},{", data)); - builder.Append("}]"); - builder.Append("},"); - builder.Append("options:{"); - builder.Append("responsive:true,"); - builder.Append($"title:{{display:{(string.IsNullOrWhiteSpace(Title) ? "false" : "true")},text:'{Title}'}},"); - builder.Append("tooltips:{mode:'index',intersect:false},"); - builder.Append("hover:{mode:'nearest',intersect:true},"); - if (Type == TypeChart.Line || Type == TypeChart.Bar) - { - builder.Append($"scales:{{"); - builder.Append($"xAxes:[{{display: true,scaleLabel:{{display:true,labelString:'{TitleX}'}}}}],"); - builder.Append($"yAxes:[{{display:true,ticks:{{{(Minimum != float.MinValue ? $"min:{Minimum},suggestedMin:{Minimum}," : "")}{(Maximum != float.MaxValue ? $"max:{Maximum},suggestedMax:{Maximum}," : "")}}},scaleLabel:{{display:true,labelString:'{TitleY}'}}}}]"); - builder.Append($"}}"); - } - builder.Append("}};"); - - builder.AppendLine($"var chart_{Id} = new Chart(document.getElementById('{Id}').getContext('2d'), config_{Id});"); - - context.VisualTree.AddScript($"chart_{Id}", builder.ToString()); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Initialize(context); - - var html = new HtmlElementScriptingCanvas() - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - if (Width > 0) - { - html.Width = Width; - html.Style = Css.Concatenate($"width: {Width}px;", html.Style); - } - - if (Height > 0) - { - html.Height = Height; - html.Style = Css.Concatenate($"height: {Height}px;", html.Style); - } - - return new HtmlElementTextContentDiv(html) { Class = "chart-container" }; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Globalization; +//using System.Linq; +//using System.Text; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; +//using WebExpress.WebCore.WebUri; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlChart : Control +// { +// /// +// /// Returns or sets the type. +// /// +// public TypeChart Type { get; set; } + +// /// +// /// Returns or sets the title. +// /// +// public string Title { get; set; } + +// /// +// /// Returns or sets the title of the x-axis. +// /// +// public string TitleX { get; set; } + +// /// +// /// Returns or sets the title of the y-axis. +// /// +// public string TitleY { get; set; } + +// /// +// /// Returns or sets the data. +// /// +// public ICollection Labels { get; set; } = new List(); + +// /// +// /// Returns or sets the width. +// /// +// public new int Width { get; set; } + +// /// +// /// Returns or sets the height. +// /// +// public new int Height { get; set; } + +// /// +// /// Returns or sets the minimum. +// /// +// public float Minimum { get; set; } = float.MinValue; + +// /// +// /// Returns or sets the maximum. +// /// +// public float Maximum { get; set; } = float.MaxValue; + +// /// +// /// Returns or sets the data. +// /// +// public ICollection Data { get; set; } = new List(); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlChart(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes the control. +// /// +// /// The context in which the control is rendered. +// public void Initialize(RenderContext context) +// { +// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(context.PageContext?.ApplicationContext?.ContextPath, "/assets/js/Chart.min.js")); +// context.VisualTree.CssLinks.Add(UriResource.Combine(context.PageContext?.ApplicationContext?.ContextPath, "/assets/css/Chart.min.css")); + +// var builder = new StringBuilder(); +// var data = new List(); +// builder.Append($"var config_{Id} = {{"); +// //if (Type != TypeChart.Polar) +// { +// builder.Append($"type:'{Type.ToType()}',"); +// } +// builder.Append("data:{"); +// builder.Append($"labels:[{string.Join(",", Labels.Select(x => $"'{x}'"))}],"); +// builder.Append("datasets:[{"); +// foreach (var v in Data) +// { +// var buf = new StringBuilder(); + +// buf.Append($"label:'{v.Title}',"); +// buf.Append($"backgroundColor:{(v.BackgroundColor.Count <= 1 ? v.BackgroundColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BackgroundColor.Select(x => $"'{x}'"))} ]")},"); +// buf.Append($"borderColor:{(v.BorderColor.Count <= 1 ? v.BorderColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BorderColor.Select(x => $"'{x}'"))} ]")},"); +// buf.Append($"data:["); +// if (v.Data != null) +// { +// buf.Append(string.Join(",", v.Data.Select(x => x.ToString(CultureInfo.InvariantCulture)))); +// } +// buf.Append($"],"); +// if (Type == TypeChart.Line) +// { +// buf.Append($"fill:'{v.Fill.ToType()}',"); +// buf.Append($"pointStyle:'{v.Point.ToType()}'"); +// } +// data.Add(buf); +// } +// builder.Append(string.Join("},{", data)); +// builder.Append("}]"); +// builder.Append("},"); +// builder.Append("options:{"); +// builder.Append("responsive:true,"); +// builder.Append($"title:{{display:{(string.IsNullOrWhiteSpace(Title) ? "false" : "true")},text:'{Title}'}},"); +// builder.Append("tooltips:{mode:'index',intersect:false},"); +// builder.Append("hover:{mode:'nearest',intersect:true},"); +// if (Type == TypeChart.Line || Type == TypeChart.Bar) +// { +// builder.Append($"scales:{{"); +// builder.Append($"xAxes:[{{display: true,scaleLabel:{{display:true,labelString:'{TitleX}'}}}}],"); +// builder.Append($"yAxes:[{{display:true,ticks:{{{(Minimum != float.MinValue ? $"min:{Minimum},suggestedMin:{Minimum}," : "")}{(Maximum != float.MaxValue ? $"max:{Maximum},suggestedMax:{Maximum}," : "")}}},scaleLabel:{{display:true,labelString:'{TitleY}'}}}}]"); +// builder.Append($"}}"); +// } +// builder.Append("}};"); + +// builder.AppendLine($"var chart_{Id} = new Chart(document.getElementById('{Id}').getContext('2d'), config_{Id});"); + +// context.VisualTree.AddScript($"chart_{Id}", builder.ToString()); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Initialize(context); + +// var html = new HtmlElementScriptingCanvas() +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// if (Width > 0) +// { +// html.Width = Width; +// html.Style = Css.Concatenate($"width: {Width}px;", html.Style); +// } + +// if (Height > 0) +// { +// html.Height = Height; +// html.Style = Css.Concatenate($"height: {Height}px;", html.Style); +// } + +// return new HtmlElementTextContentDiv(html) { Class = "chart-container" }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs index 919ec0b4..f7bdc779 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs @@ -1,44 +1,44 @@ -ο»Ώusing System.Collections.Generic; +ο»Ώ//using System.Collections.Generic; -namespace WebExpress.WebUI.WebControl -{ - public class ControlChartDataset - { - /// - /// Returns or sets the title. - /// - public string Title { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlChartDataset +// { +// /// +// /// Returns or sets the title. +// /// +// public string Title { get; set; } - /// - /// Returns or sets the data. - /// - public float[] Data { get; set; } +// /// +// /// Returns or sets the data. +// /// +// public float[] Data { get; set; } - /// - /// Returns or sets the background color. - /// - public List BackgroundColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; +// /// +// /// Returns or sets the background color. +// /// +// public List BackgroundColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; - /// - /// Returns or sets the frame color. - /// - public List BorderColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; +// /// +// /// Returns or sets the frame color. +// /// +// public List BorderColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; - /// - /// Returns or sets how the data series are populated. - /// - public TypeFillChart Fill { get; set; } = TypeFillChart.None; +// /// +// /// Returns or sets how the data series are populated. +// /// +// public TypeFillChart Fill { get; set; } = TypeFillChart.None; - /// - /// Returns or sets how the data series are populated. - /// - public TypePointChart Point { get; set; } = TypePointChart.Circle; +// /// +// /// Returns or sets how the data series are populated. +// /// +// public TypePointChart Point { get; set; } = TypePointChart.Circle; - /// - /// Initializes a new instance of the class. - /// - public ControlChartDataset() - { - } - } -} +// /// +// /// Initializes a new instance of the class. +// /// +// public ControlChartDataset() +// { +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs index c4980585..d33df261 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs @@ -1,318 +1,318 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlDropdown : Control, IControlNavigationItem - { - /// - /// Returns or sets the content. - /// - public List Items { get; private set; } = new List(); - - /// - /// Returns or sets the background color. - /// - public new PropertyColorButton BackgroundColor - { - get => (PropertyColorButton)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); - } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the outline property - /// - public bool Outline { get; set; } - - /// - /// Returns or sets whether the button should take up the full width. - /// - public TypeBlockButton Block - { - get => (TypeBlockButton)GetProperty(TypeBlockButton.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets an indicator that indicates that a menu is present. - /// - public TypeToggleDropdown Toogle - { - get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the tooltip. - /// - public string Title { get; set; } - - /// - /// Returns or sets the value. - /// - public string Value { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the activation status of the button. - /// - public TypeActive Active - { - get => (TypeActive)GetProperty(TypeActive.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the orientation of the menu. - /// - public TypeAlignmentDropdownMenu AlignmentMenu - { - get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the image. - /// - public string Image { get; set; } - - /// - /// Returns or sets the height. - /// - public new int Height { get; set; } = -1; - - /// - /// Returns or sets the width. - /// - public new int Width { get; set; } = -1; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlDropdown(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlDropdown(string id, params IControlDropdownItem[] content) - : base(id) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlDropdown(params IControlDropdownItem[] content) - : base(null) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlDropdown(string id, IEnumerable content) - : base(id) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlDropdown(IEnumerable content) - : base(null) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Adds a new item. - /// - /// The item. - public void Add(IControlDropdownItem item) - { - Items.Add(item); - } - - /// - /// Adds a new separator. - /// - public void AddSeperator() - { - Items.Add(null); - } - - /// - /// Adds a new head. - /// - /// The headline text. - public void AddHeader(string text) - { - Items.Add(new ControlDropdownItemHeader() { Text = text }); - } - - /// - /// Initialization - /// - private void Init() - { - Size = TypeSizeButton.Default; - } - - /// - /// Adds items. - /// - /// The items which should be added. - public void Add(params IControlDropdownItem[] item) - { - Items.AddRange(item); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("dropdown", Margin.ToClass()), - Role = Role - }; - - if (Image == null) - { - var button = new HtmlElementFieldButton() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles(), - Title = Title - }; - button.AddUserAttribute("data-bs-toggle", "dropdown"); - button.AddUserAttribute("aria-expanded", "false"); - - if (Icon != null && Icon.HasIcon) - { - button.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - button.Elements.Add(new HtmlText(Text)); - } - - html.Elements.Add(button); - } - else - { - var button = new HtmlElementMultimediaImg() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles(), - Src = Image.ToString() - }; - button.AddUserAttribute("data-bs-toggle", "dropdown"); - button.AddUserAttribute("aria-expanded", "false"); - - if (Height > 0) - { - button.Height = Height; - } - - if (Width > 0) - { - button.Width = Width; - } - - html.Elements.Add(button); - } - - html.Elements.Add - ( - new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(context) : - new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } - ) - ) - { - Class = Css.Concatenate - ( - "dropdown-menu", - AlignmentMenu.ToClass() - ) - } - ); - - var modals = Items.Where(x => x is ControlDropdownItemLink) - .Select(x => x as ControlDropdownItemLink) - .Select(x => x.Modal) - .Where(x => x.Type == TypeModal.Modal) - .Select(x => x.Modal.Render(context)); - - return new HtmlList(html, modals); - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlDropdown : Control, IControlNavigationItem +// { +// /// +// /// Returns or sets the content. +// /// +// public List Items { get; private set; } = new List(); + +// /// +// /// Returns or sets the background color. +// /// +// public new PropertyColorButton BackgroundColor +// { +// get => (PropertyColorButton)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); +// } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeButton Size +// { +// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the outline property +// /// +// public bool Outline { get; set; } + +// /// +// /// Returns or sets whether the button should take up the full width. +// /// +// public TypeBlockButton Block +// { +// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets an indicator that indicates that a menu is present. +// /// +// public TypeToggleDropdown Toogle +// { +// get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the tooltip. +// /// +// public string Title { get; set; } + +// /// +// /// Returns or sets the value. +// /// +// public string Value { get; set; } + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Returns or sets the activation status of the button. +// /// +// public TypeActive Active +// { +// get => (TypeActive)GetProperty(TypeActive.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the orientation of the menu. +// /// +// public TypeAlignmentDropdownMenu AlignmentMenu +// { +// get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the image. +// /// +// public string Image { get; set; } + +// /// +// /// Returns or sets the height. +// /// +// public new int Height { get; set; } = -1; + +// /// +// /// Returns or sets the width. +// /// +// public new int Width { get; set; } = -1; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlDropdown(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlDropdown(string id, params IControlDropdownItem[] content) +// : base(id) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlDropdown(params IControlDropdownItem[] content) +// : base(null) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlDropdown(string id, IEnumerable content) +// : base(id) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlDropdown(IEnumerable content) +// : base(null) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Adds a new item. +// /// +// /// The item. +// public void Add(IControlDropdownItem item) +// { +// Items.Add(item); +// } + +// /// +// /// Adds a new separator. +// /// +// public void AddSeperator() +// { +// Items.Add(null); +// } + +// /// +// /// Adds a new head. +// /// +// /// The headline text. +// public void AddHeader(string text) +// { +// Items.Add(new ControlDropdownItemHeader() { Text = text }); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Size = TypeSizeButton.Default; +// } + +// /// +// /// Adds items. +// /// +// /// The items which should be added. +// public void Add(params IControlDropdownItem[] item) +// { +// Items.AddRange(item); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("dropdown", Margin.ToClass()), +// Role = Role +// }; + +// if (Image == null) +// { +// var button = new HtmlElementFieldButton() +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), +// Style = GetStyles(), +// Title = Title +// }; +// button.AddUserAttribute("data-bs-toggle", "dropdown"); +// button.AddUserAttribute("aria-expanded", "false"); + +// if (Icon != null && Icon.HasIcon) +// { +// button.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// button.Elements.Add(new HtmlText(Text)); +// } + +// html.Elements.Add(button); +// } +// else +// { +// var button = new HtmlElementMultimediaImg() +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), +// Style = GetStyles(), +// Src = Image.ToString() +// }; +// button.AddUserAttribute("data-bs-toggle", "dropdown"); +// button.AddUserAttribute("aria-expanded", "false"); + +// if (Height > 0) +// { +// button.Height = Height; +// } + +// if (Width > 0) +// { +// button.Width = Width; +// } + +// html.Elements.Add(button); +// } + +// html.Elements.Add +// ( +// new HtmlElementTextContentUl +// ( +// Items.Select +// ( +// x => +// x == null || x is ControlDropdownItemDivider || x is ControlLine ? +// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : +// x is ControlDropdownItemHeader ? +// x.Render(context) : +// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } +// ) +// ) +// { +// Class = Css.Concatenate +// ( +// "dropdown-menu", +// AlignmentMenu.ToClass() +// ) +// } +// ); + +// var modals = Items.Where(x => x is ControlDropdownItemLink) +// .Select(x => x as ControlDropdownItemLink) +// .Select(x => x.Modal) +// .Where(x => x.Type == TypeModal.Modal) +// .Select(x => x.Modal.Render(context)); + +// return new HtmlList(html, modals); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs index 2ae1da7c..ec1e7d13 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs @@ -1,43 +1,43 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlDropdownItemDivider : Control, IControlDropdownItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlDropdownItemDivider(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlDropdownItemDivider : Control, IControlDropdownItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlDropdownItemDivider(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("dropdown-divider", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("dropdown-divider", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs index 17bde0a1..85ff81cc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs @@ -1,59 +1,59 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlDropdownItemHeader : Control, IControlDropdownItem - { - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlDropdownItemHeader : Control, IControlDropdownItem +// { +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlDropdownItemHeader(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlDropdownItemHeader(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlDropdownItemHeader(string id, string text) - : base(id) - { - Text = text; +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlDropdownItemHeader(string id, string text) +// : base(id) +// { +// Text = text; - Init(); - } +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementTextContentLi(new HtmlText(Text)) - { - Id = Id, - Class = Css.Concatenate("dropdown-header", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementTextContentLi(new HtmlText(Text)) +// { +// Id = Id, +// Class = Css.Concatenate("dropdown-header", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index 82b9c6ec..ddca8dc4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -1,88 +1,88 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlDropdownItemLink : ControlLink, IControlDropdownItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlDropdownItemLink(string id = null) - : base(id) - { - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlDropdownItemLink : ControlLink, IControlDropdownItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlDropdownItemLink(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var param = GetParams(context?.Page); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var param = ""; // GetParams(context?.Page); - var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) - { - Id = Id, - Class = Css.Concatenate("link", GetClasses()), - Style = GetStyles(), - Role = Role, - Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), - Target = Target, - Title = context.I18N(Title), - OnClick = OnClick?.ToString() - }; +// var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = Css.Concatenate("link", GetClasses()), +// Style = GetStyles(), +// Role = Role, +// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), +// Target = Target, +// Title = I18N.Translate(Title), +// OnClick = OnClick?.ToString() +// }; - if (Icon != null && Icon.HasIcon) - { - html.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None) - }.Render(context)); - } +// if (Icon != null && Icon.HasIcon) +// { +// html.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None) +// }.Render(context)); +// } - if (!string.IsNullOrWhiteSpace(Text)) - { - html.Elements.Add(new HtmlText(InternationalizationManager.I18N(context.Culture, Text))); - } +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); +// } - if (Modal == null || Modal.Type == TypeModal.None) - { +// if (Modal == null || Modal.Type == TypeModal.None) +// { - } - else if (Modal.Type == TypeModal.Form) - { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - html.Href = "#"; - } - else if (Modal.Type == TypeModal.Brwoser) - { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - html.Href = "#"; - } - else if (Modal.Type == TypeModal.Modal) - { - html.AddUserAttribute("data-bs-toggle", "modal"); - html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - } +// } +// else if (Modal.Type == TypeModal.Form) +// { +// html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// html.Href = "#"; +// } +// else if (Modal.Type == TypeModal.Brwoser) +// { +// html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// html.Href = "#"; +// } +// else if (Modal.Type == TypeModal.Modal) +// { +// html.AddUserAttribute("data-bs-toggle", "modal"); +// html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); +// } - if (!string.IsNullOrWhiteSpace(Tooltip)) - { - html.AddUserAttribute("data-bs-toggle", "tooltip"); - } +// if (!string.IsNullOrWhiteSpace(Tooltip)) +// { +// html.AddUserAttribute("data-bs-toggle", "tooltip"); +// } - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index ba665c1f..cef87263 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -1,630 +1,601 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebApp.WebSection; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebScope; -using WebExpress.WebUI.WebFragment; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a form with various input fields and controls. - /// - public class ControlForm : Control, IControlForm, IScope - { - /// - /// Returns the form items. - /// - private List _items = []; - - /// - /// Returns the preferences form control buttons. - /// - private List _preferencesButtons = []; - - /// - /// Returns the primary form control buttons. - /// - private List _primaryButtons = []; - - /// - /// Returns the secondary form control buttons. - /// - private List _secondaryButtons = []; - - /// - /// Returns the preferences controls. - /// - private List _preferencesControls = []; - - /// - /// Returns the primary controls. - /// - private List _primaryControls = []; - - /// - /// Returns the secondary controls. - /// - private List _secondaryControls = []; - - /// - /// Event to validate the input values. - /// - public event EventHandler Validation; - - /// - /// Event nach Abschluss der Validation - /// - public event EventHandler Validated; - - /// - /// Event is raised when the form has been initialized. - /// - public event EventHandler InitializeForm; - - /// - /// Event is raised when the form's data needs to be determined. - /// - public event EventHandler FillForm; - - /// - /// Event is raised when the form is about to be processed. - /// - public event EventHandler ProcessForm; - - /// - /// Event is raised when the form is to be processed and the next data is to be loaded. - /// - public event EventHandler ProcessAndNextForm; - - /// - /// Returns or sets the name of the form. - /// - public string Name { get; set; } - - /// - /// Returns or sets the target uri. - /// - public string Uri { get; set; } - - /// - /// Returns or sets the redirect uri. - /// - public string RedirectUri { get; set; } - - /// - /// Returns or sets the form layout. - /// - public virtual TypeLayoutForm FormLayout { get; set; } = TypeLayoutForm.Default; - - /// - /// Returns or sets the item layout. - /// - public virtual TypeLayoutFormItem ItemLayout { get; set; } = TypeLayoutFormItem.Vertical; - - /// - /// Returns or sets the hidden field that contains the id. - /// - public ControlFormItemInputHidden FormId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) - { - Name = "form-id" - }; - - /// - /// Returns or sets the hidden field that contains the submit method. - /// - public ControlFormItemInputHidden SubmitType { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) - { - Name = "form-submit-type", - Value = "update" - }; - - /// - /// Returns or sets the request method. - /// - public RequestMethod Method { get; set; } = RequestMethod.POST; - - /// - /// Returns or sets the header preferences section. - /// - protected List HeaderPreferences { get; } = []; - - /// - /// Returns or sets the header primary section. - /// - protected List HeaderPrimary { get; } = []; - - /// - /// Returns or sets the header secondary section. - /// - protected List HeaderSecondary { get; } = []; - - /// - /// Returns or sets the button panel preferences section. - /// - protected List ButtonPanelPreferences { get; } = []; - - /// - /// Returns or sets the button panel primary section. - /// - protected List ButtonPanelPrimary { get; } = []; - - /// - /// Returns or sets the button panel secondary section. - /// - protected List ButtonPanelSecondary { get; } = []; - - /// - /// Returns or sets the footer preferences section. - /// - protected List FooterPreferences { get; } = []; - - /// - /// Returns or sets the footer primary section. - /// - protected List FooterPrimary { get; } = []; - - /// - /// Returns or sets the footer secondary section. - /// - protected List FooterSecondary { get; } = []; - - /// - /// Returns the form items. - /// - public IEnumerable Items => _items; - - /// - /// Returns the form buttons. - /// - public IEnumerable Buttons => _preferencesButtons.Union(_primaryButtons).Union(_secondaryButtons); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlForm(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The controls that are associated with the form. - public ControlForm(string id, params ControlFormItem[] items) - : this(id) - { - _items.AddRange(items); - } - - /// - /// Initializes a new instance of the class. - /// - /// The controls that are associated with the form. - public ControlForm(params ControlFormItem[] items) - : this(null, items) - { - } - - /// - /// Initializes the form. - /// - /// The context in which the control is rendered. - public virtual void Initialize(RenderContextForm context) - { - var fm = ComponentManager.GetComponent(); - - // check id - if (string.IsNullOrWhiteSpace(Id)) - { - context.ApplicationContext?.PluginContext.Host.Log.Warning(InternationalizationManager.I18N("webexpress.webui:form.empty.id")); - } - - FormId.Value = Id; - - // header - HeaderPreferences.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPreferences, context.Page, [GetType().FullName])); - HeaderPrimary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPrimary, context.Page, [GetType().FullName])); - HeaderSecondary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderSecondary, context.Page, [GetType().FullName])); - - // footer - FooterPreferences.AddRange(fm.GetCacheableFragments(SectionControl.FooterPreferences, context.Page, [GetType().FullName])); - FooterPrimary.AddRange(fm.GetCacheableFragments(SectionControl.FooterPrimary, context.Page, [GetType().FullName])); - FooterSecondary.AddRange(fm.GetCacheableFragments(SectionControl.FooterSecondary, context.Page, [GetType().FullName])); - } - - /// - /// Filling the form. - /// - /// The context in which the control is rendered. - public virtual void Fill(RenderContextForm context) - { - OnFill(context); - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - /// True if all form items are valid, false otherwise. - public virtual bool Validate(RenderContextForm context) - { - var valid = true; - var validationResults = context.ValidationResults as List; - - foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) - { - v.Validate(context); - - if (v.ValidationResult == TypesInputValidity.Error) - { - valid = false; - } - - validationResults.AddRange(v.ValidationResults); - } - - var args = new ValidationEventArgs() { Value = null, Context = context }; - OnValidation(args); - - validationResults.AddRange(args.Results); - - if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - valid = false; - } - - var validatedArgs = new ValidationResultEventArgs(valid); - validatedArgs.Results.AddRange(validationResults); - - OnValidated(validatedArgs); - - return valid; - } - - /// - /// Instructs to reload the initial form data. - /// - public void Reset() - { - Fill(null); - } - - /// - /// Pre-processing of the form. - /// - /// The context in which the control is rendered. - public virtual void PreProcess(RenderContextForm context) - { - - } - - /// - /// Processing of the form. - /// - /// The context in which the control is rendered. - public virtual void Process(RenderContextForm context) - { - OnProcess(context); - - if (!string.IsNullOrWhiteSpace(RedirectUri?.ToString())) - { - context.Page.Redirecting(RedirectUri); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return Render(context, Items); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The form items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, IEnumerable items) - { - var renderContext = new RenderContextForm(context, this); - var fill = false; - var process = false; - - // check if and how the form was submitted - if (context.Request.GetParameter("form-id")?.Value == Id && context.Request.HasParameter("form-submit-type")) - { - var value = context.Request.GetParameter("form-submit-type")?.Value; - switch (value) - { - case "submit": - process = true; - fill = false; - break; - case "reset": - process = false; - fill = true; - break; - case "update": - default: - break; - } - } - else - { - // first call - fill = true; - process = false; - } - - // initialization - Initialize(renderContext); - foreach (var item in items) - { - item.Initialize(renderContext); - } - foreach (var item in Buttons) - { - item.Initialize(renderContext); - } - OnInitialize(renderContext); - - // fill the form with data - if (fill) - { - Fill(renderContext); - } - - // preprocessing - PreProcess(renderContext); - - // process form (e.g. save form data) - if (process && Validate(renderContext)) - { - Process(renderContext); - } - - // generate html - var form = new HtmlElementFormForm() - { - Id = Id, - Class = FormLayout == TypeLayoutForm.Inline ? Css.Concatenate("form-inline", GetClasses()) : GetClasses(), - Style = GetStyles(), - Role = Role, - Action = Uri?.ToString() ?? renderContext.Uri?.ToString(), - Method = Method.ToString(), - Enctype = TypeEnctype.None - }; - - form.Elements.Add(FormId.Render(renderContext)); - form.Elements.Add(SubmitType.Render(renderContext)); - var header = new HtmlElementSectionHeader(); - header.Elements.Add(new ControlProgressBar() - { - Format = TypeFormatProgress.Animated, - Color = new PropertyColorProgress(TypeColorProgress.Success), - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three), - Styles = { "height: 3px;", "display: none;" }, - Value = 0 - }.Render(renderContext)); - - header.Elements.AddRange(HeaderPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - header.Elements.AddRange(HeaderSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - - foreach (var v in renderContext.ValidationResults) - { - var bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Default); - - switch (v.Type) - { - case TypesInputValidity.Error: - bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Danger); - break; - case TypesInputValidity.Warning: - bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Warning); - break; - } - - header.Elements.Add(new ControlAlert() - { - BackgroundColor = bgColor, - Text = context.I18N(v.Text), - Dismissible = TypeDismissibleAlert.Dismissible, - Fade = TypeFade.FadeShow - }.Render(renderContext)); - } - - foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) - { - form.Elements.Add(item.Render(renderContext)); - } - - var main = new HtmlElementSectionMain(); - - var group = default(ControlFormItemGroup); - - group = ItemLayout switch - { - TypeLayoutFormItem.Horizontal => new ControlFormItemGroupHorizontal(), - TypeLayoutFormItem.Mix => new ControlFormItemGroupMix(), - _ => new ControlFormItemGroupVertical(), - }; - - foreach (var item in items.Where(x => x is not ControlFormItemInputHidden)) - { - group.Items.Add(item); - } - - main.Elements.Add(group.Render(renderContext)); - - var buttonPannel = new HtmlElementTextContentDiv(); - buttonPannel.Elements.AddRange(Buttons.Select(x => x.Render(renderContext))); - - var footer = new HtmlElementSectionFooter(); - footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - - footer.Elements.AddRange(FooterPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - footer.Elements.AddRange(FooterSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - - form.Elements.Add(header); - form.Elements.Add(main); - form.Elements.Add(buttonPannel); - form.Elements.Add(footer); - - form.Elements.AddRange(renderContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); - - context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{Method.ToString()}');"); - - return form; - } - - /// - /// Adds a form control. - /// - /// The form item. - public void Add(params ControlFormItem[] item) - { - _items.AddRange(item); - } - - /// - /// Adds a preferences control. - /// - /// The controls. - public void AddPreferencesControl(params ControlFormItem[] controls) - { - _preferencesControls.AddRange(controls); - } - - /// - /// Adds a preferences form control button. - /// - /// The form buttons. - public void AddPreferencesButton(params ControlFormItemButton[] buttons) - { - _preferencesButtons.AddRange(buttons); - } - - /// - /// Adds a primary control. - /// - /// The controls. - public void AddPrimaryControl(params ControlFormItem[] controls) - { - _primaryControls.AddRange(controls); - } - - /// - /// Adds a primary form control button. - /// - /// The form buttons. - public void AddPrimaryButton(params ControlFormItemButton[] buttons) - { - _primaryButtons.AddRange(buttons); - } - - /// - /// Adds a secondary control. - /// - /// The controls. - public void AddSecondaryControl(params ControlFormItem[] controls) - { - _secondaryControls.AddRange(controls); - } - - /// - /// Adds a secondary form control button. - /// - /// The form buttons. - public void AddSecondaryButton(params ControlFormItemButton[] buttons) - { - _secondaryButtons.AddRange(buttons); - } - - /// - /// Removes a form control item from the form. - /// - /// The form item. - public void Remove(ControlFormItem formItem) - { - _items.Remove(formItem); - } - - /// - /// Removes a form control button from the form. - /// - /// The form button. - public void RemoveButton(ControlFormItemButton button) - { - _preferencesButtons.Remove(button); - _primaryButtons.Remove(button); - _secondaryButtons.Remove(button); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcess(RenderContextForm context) - { - ProcessForm?.Invoke(this, new FormEventArgs() { Context = context }); - } - - /// - /// Raises the process event. - /// - /// The context in which the control is rendered. - protected virtual void OnProcessAndNextForm(RenderContextForm context) - { - ProcessAndNextForm?.Invoke(this, new FormEventArgs() { Context = context }); - } - - /// - /// Raises the Initializations event. - /// - /// The context in which the control is rendered. - protected virtual void OnInitialize(RenderContextForm context) - { - InitializeForm?.Invoke(this, new FormEventArgs() { Context = context }); - } - - /// - /// Raises the data delivery event. - /// - /// The context in which the control is rendered. - protected virtual void OnFill(RenderContextForm context) - { - FillForm?.Invoke(this, new FormEventArgs() { Context = context }); - } - - /// - /// Raises the validation event. - /// - /// The event argument. - protected virtual void OnValidation(ValidationEventArgs e) - { - Validation?.Invoke(this, e); - } - - /// - /// Raises the Validated event. - /// - /// The event argument. - protected virtual void OnValidated(ValidationResultEventArgs e) - { - Validated?.Invoke(this, e); - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebFragment; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebMessage; +//using WebExpress.WebCore.WebPage; +//using WebExpress.WebCore.WebScope; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Represents a form with various input fields and controls. +// /// +// public class ControlForm : Control, IControlForm, IScope +// { +// private readonly List _items = []; +// private readonly List _preferencesButtons = []; +// private readonly List _primaryButtons = []; +// private readonly List _secondaryButtons = []; +// private readonly List _preferencesControls = []; +// private readonly List _primaryControls = []; +// private readonly List _secondaryControls = []; + +// /// +// /// Event to validate the input values. +// /// +// public event EventHandler Validation; + +// /// +// /// Event nach Abschluss der Validation +// /// +// public event EventHandler Validated; + +// /// +// /// Event is raised when the form has been initialized. +// /// +// public event EventHandler InitializeForm; + +// /// +// /// Event is raised when the form's data needs to be determined. +// /// +// public event EventHandler FillForm; + +// /// +// /// Event is raised when the form is about to be processed. +// /// +// public event EventHandler ProcessForm; + +// /// +// /// Event is raised when the form is to be processed and the next data is to be loaded. +// /// +// public event EventHandler ProcessAndNextForm; + +// /// +// /// Returns or sets the name of the form. +// /// +// public string Name { get; set; } + +// /// +// /// Returns or sets the target uri. +// /// +// public string Uri { get; set; } + +// /// +// /// Returns or sets the redirect uri. +// /// +// public string RedirectUri { get; set; } + +// /// +// /// Returns or sets the form layout. +// /// +// public virtual TypeLayoutForm FormLayout { get; set; } = TypeLayoutForm.Default; + +// /// +// /// Returns or sets the item layout. +// /// +// public virtual TypeLayoutFormItem ItemLayout { get; set; } = TypeLayoutFormItem.Vertical; + +// /// +// /// Returns or sets the hidden field that contains the id. +// /// +// public ControlFormItemInputHidden FormId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) +// { +// Name = "form-id" +// }; + +// /// +// /// Returns or sets the hidden field that contains the submit method. +// /// +// public ControlFormItemInputHidden SubmitType { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) +// { +// Name = "form-submit-type", +// Value = "update" +// }; + +// /// +// /// Returns or sets the request method. +// /// +// public RequestMethod Method { get; set; } = RequestMethod.POST; + +// /// +// /// Returns or sets the header preferences section. +// /// +// protected List HeaderPreferences { get; } = []; + +// /// +// /// Returns or sets the header primary section. +// /// +// protected List HeaderPrimary { get; } = []; + +// /// +// /// Returns or sets the header secondary section. +// /// +// protected List HeaderSecondary { get; } = []; + +// /// +// /// Returns or sets the button panel preferences section. +// /// +// protected List ButtonPanelPreferences { get; } = []; + +// /// +// /// Returns or sets the button panel primary section. +// /// +// protected List ButtonPanelPrimary { get; } = []; + +// /// +// /// Returns or sets the button panel secondary section. +// /// +// protected List ButtonPanelSecondary { get; } = []; + +// /// +// /// Returns or sets the footer preferences section. +// /// +// protected List FooterPreferences { get; } = []; + +// /// +// /// Returns or sets the footer primary section. +// /// +// protected List FooterPrimary { get; } = []; + +// /// +// /// Returns or sets the footer secondary section. +// /// +// protected List FooterSecondary { get; } = []; + +// /// +// /// Returns the form items. +// /// +// public IEnumerable Items => _items; + +// /// +// /// Returns the form buttons. +// /// +// public IEnumerable Buttons => _preferencesButtons.Union(_primaryButtons).Union(_secondaryButtons); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlForm(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The controls that are associated with the form. +// public ControlForm(string id, params ControlFormItem[] items) +// : this(id) +// { +// _items.AddRange(items); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The controls that are associated with the form. +// public ControlForm(params ControlFormItem[] items) +// : this(null, items) +// { +// } + +// /// +// /// Initializes the form. +// /// +// /// The context in which the control is rendered. +// public virtual void Initialize(RenderContextForm context) +// { +// //var fm = ComponentHub.GetComponent(); + +// //// check id +// //if (string.IsNullOrWhiteSpace(Id)) +// //{ +// // context.ApplicationContext?.PluginContext.Host.Log.Warning(I18N.Translate("webexpress.webui:form.empty.id")); +// //} + +// //FormId.Value = Id; + +// //// header +// //HeaderPreferences.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPreferences, context.Page, [GetType().FullName])); +// //HeaderPrimary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPrimary, context.Page, [GetType().FullName])); +// //HeaderSecondary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderSecondary, context.Page, [GetType().FullName])); + +// //// footer +// //FooterPreferences.AddRange(fm.GetCacheableFragments(SectionControl.FooterPreferences, context.Page, [GetType().FullName])); +// //FooterPrimary.AddRange(fm.GetCacheableFragments(SectionControl.FooterPrimary, context.Page, [GetType().FullName])); +// //FooterSecondary.AddRange(fm.GetCacheableFragments(SectionControl.FooterSecondary, context.Page, [GetType().FullName])); +// } + +// /// +// /// Filling the form. +// /// +// /// The context in which the control is rendered. +// public virtual void Fill(RenderContextForm context) +// { +// OnFill(context); +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// /// True if all form items are valid, false otherwise. +// public virtual bool Validate(RenderContextForm context) +// { +// var valid = true; +// var validationResults = context.ValidationResults as List; + +// foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) +// { +// v.Validate(context); + +// if (v.ValidationResult == TypesInputValidity.Error) +// { +// valid = false; +// } + +// validationResults.AddRange(v.ValidationResults); +// } + +// var args = new ValidationEventArgs() { Value = null, Context = context }; +// OnValidation(args); + +// validationResults.AddRange(args.Results); + +// if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) +// { +// valid = false; +// } + +// var validatedArgs = new ValidationResultEventArgs(valid); +// validatedArgs.Results.AddRange(validationResults); + +// OnValidated(validatedArgs); + +// return valid; +// } + +// /// +// /// Instructs to reload the initial form data. +// /// +// public void Reset() +// { +// Fill(null); +// } + +// /// +// /// Pre-processing of the form. +// /// +// /// The context in which the control is rendered. +// public virtual void PreProcess(RenderContextForm context) +// { + +// } + +// /// +// /// Processing of the form. +// /// +// /// The context in which the control is rendered. +// public virtual void Process(RenderContextForm context) +// { +// //OnProcess(context); + +// //if (!string.IsNullOrWhiteSpace(RedirectUri?.ToString())) +// //{ +// // context.Page.Redirecting(RedirectUri); +// //} +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return Render(context, Items); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The form items. +// /// The control as html. +// public virtual IHtmlNode Render(IRenderContext context, IEnumerable items) +// { +// var renderContext = new RenderContextForm(context, this); +// var fill = false; +// var process = false; + +// // check if and how the form was submitted +// if (context.Request.GetParameter("form-id")?.Value == Id && context.Request.HasParameter("form-submit-type")) +// { +// var value = context.Request.GetParameter("form-submit-type")?.Value; +// switch (value) +// { +// case "submit": +// process = true; +// fill = false; +// break; +// case "reset": +// process = false; +// fill = true; +// break; +// case "update": +// default: +// break; +// } +// } +// else +// { +// // first call +// fill = true; +// process = false; +// } + +// // initialization +// Initialize(renderContext); +// foreach (var item in items) +// { +// item.Initialize(renderContext); +// } +// foreach (var item in Buttons) +// { +// item.Initialize(renderContext); +// } +// OnInitialize(renderContext); + +// // fill the form with data +// if (fill) +// { +// Fill(renderContext); +// } + +// // preprocessing +// PreProcess(renderContext); + +// // process form (e.g. save form data) +// if (process && Validate(renderContext)) +// { +// Process(renderContext); +// } + +// // generate html +// var form = new HtmlElementFormForm() +// { +// Id = Id, +// Class = FormLayout == TypeLayoutForm.Inline ? Css.Concatenate("form-inline", GetClasses()) : GetClasses(), +// Style = GetStyles(), +// Role = Role, +// Action = Uri?.ToString() ?? renderContext.Uri?.ToString(), +// Method = Method.ToString(), +// Enctype = TypeEnctype.None +// }; + +// form.Elements.Add(FormId.Render(renderContext)); +// form.Elements.Add(SubmitType.Render(renderContext)); +// var header = new HtmlElementSectionHeader(); +// header.Elements.Add(new ControlProgressBar() +// { +// Format = TypeFormatProgress.Animated, +// Color = new PropertyColorProgress(TypeColorProgress.Success), +// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three), +// Styles = { "height: 3px;", "display: none;" }, +// Value = 0 +// }.Render(renderContext)); + +// //header.Elements.AddRange(HeaderPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); +// //header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); +// //header.Elements.AddRange(HeaderSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + +// foreach (var v in renderContext.ValidationResults) +// { +// var bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Default); + +// switch (v.Type) +// { +// case TypesInputValidity.Error: +// bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Danger); +// break; +// case TypesInputValidity.Warning: +// bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Warning); +// break; +// } + +// header.Elements.Add(new ControlAlert() +// { +// BackgroundColor = bgColor, +// Text = I18N.Translate(v.Text), +// Dismissible = TypeDismissibleAlert.Dismissible, +// Fade = TypeFade.FadeShow +// }.Render(renderContext)); +// } + +// foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) +// { +// form.Elements.Add(item.Render(renderContext)); +// } + +// var main = new HtmlElementSectionMain(); + +// var group = default(ControlFormItemGroup); + +// group = ItemLayout switch +// { +// TypeLayoutFormItem.Horizontal => new ControlFormItemGroupHorizontal(), +// TypeLayoutFormItem.Mix => new ControlFormItemGroupMix(), +// _ => new ControlFormItemGroupVertical(), +// }; + +// foreach (var item in items.Where(x => x is not ControlFormItemInputHidden)) +// { +// group.Items.Add(item); +// } + +// main.Elements.Add(group.Render(renderContext)); + +// var buttonPannel = new HtmlElementTextContentDiv(); +// buttonPannel.Elements.AddRange(Buttons.Select(x => x.Render(renderContext))); + +// var footer = new HtmlElementSectionFooter(); +// //footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + +// //footer.Elements.AddRange(FooterPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); +// //footer.Elements.AddRange(FooterSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + +// form.Elements.Add(header); +// form.Elements.Add(main); +// form.Elements.Add(buttonPannel); +// form.Elements.Add(footer); + +// form.Elements.AddRange(renderContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); + +// context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{Method.ToString()}');"); + +// return form; +// } + +// /// +// /// Adds a form control. +// /// +// /// The form item. +// public void Add(params ControlFormItem[] item) +// { +// _items.AddRange(item); +// } + +// /// +// /// Adds a preferences control. +// /// +// /// The controls. +// public void AddPreferencesControl(params ControlFormItem[] controls) +// { +// _preferencesControls.AddRange(controls); +// } + +// /// +// /// Adds a preferences form control button. +// /// +// /// The form buttons. +// public void AddPreferencesButton(params ControlFormItemButton[] buttons) +// { +// _preferencesButtons.AddRange(buttons); +// } + +// /// +// /// Adds a primary control. +// /// +// /// The controls. +// public void AddPrimaryControl(params ControlFormItem[] controls) +// { +// _primaryControls.AddRange(controls); +// } + +// /// +// /// Adds a primary form control button. +// /// +// /// The form buttons. +// public void AddPrimaryButton(params ControlFormItemButton[] buttons) +// { +// _primaryButtons.AddRange(buttons); +// } + +// /// +// /// Adds a secondary control. +// /// +// /// The controls. +// public void AddSecondaryControl(params ControlFormItem[] controls) +// { +// _secondaryControls.AddRange(controls); +// } + +// /// +// /// Adds a secondary form control button. +// /// +// /// The form buttons. +// public void AddSecondaryButton(params ControlFormItemButton[] buttons) +// { +// _secondaryButtons.AddRange(buttons); +// } + +// /// +// /// Removes a form control item from the form. +// /// +// /// The form item. +// public void Remove(ControlFormItem formItem) +// { +// _items.Remove(formItem); +// } + +// /// +// /// Removes a form control button from the form. +// /// +// /// The form button. +// public void RemoveButton(ControlFormItemButton button) +// { +// _preferencesButtons.Remove(button); +// _primaryButtons.Remove(button); +// _secondaryButtons.Remove(button); +// } + +// /// +// /// Raises the process event. +// /// +// /// The context in which the control is rendered. +// protected virtual void OnProcess(RenderContextForm context) +// { +// ProcessForm?.Invoke(this, new FormEventArgs() { Context = context }); +// } + +// /// +// /// Raises the process event. +// /// +// /// The context in which the control is rendered. +// protected virtual void OnProcessAndNextForm(RenderContextForm context) +// { +// ProcessAndNextForm?.Invoke(this, new FormEventArgs() { Context = context }); +// } + +// /// +// /// Raises the Initializations event. +// /// +// /// The context in which the control is rendered. +// protected virtual void OnInitialize(RenderContextForm context) +// { +// InitializeForm?.Invoke(this, new FormEventArgs() { Context = context }); +// } + +// /// +// /// Raises the data delivery event. +// /// +// /// The context in which the control is rendered. +// protected virtual void OnFill(RenderContextForm context) +// { +// FillForm?.Invoke(this, new FormEventArgs() { Context = context }); +// } + +// /// +// /// Raises the validation event. +// /// +// /// The event argument. +// protected virtual void OnValidation(ValidationEventArgs e) +// { +// Validation?.Invoke(this, e); +// } + +// /// +// /// Raises the Validated event. +// /// +// /// The event argument. +// protected virtual void OnValidated(ValidationResultEventArgs e) +// { +// Validated?.Invoke(this, e); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs index dc343b49..901eb6ca 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs @@ -1,50 +1,57 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public abstract class ControlFormItem : Control - { - /// - /// Returns or sets the name of the input field. - /// - public string Name { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Abstract base class for form items. +// /// +// /// +// /// This class provides the base functionality for form items, including properties for the name of the input field, +// /// initialization, and rendering to HTML. +// /// +// public abstract class ControlFormItem : Control +// { +// /// +// /// Returns or sets the name of the input field. +// /// +// public string Name { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItem(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItem(string id = null) +// : base(id) +// { +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public abstract void Initialize(RenderContextForm context); +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public abstract void Initialize(RenderContextForm context); - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public abstract IHtmlNode Render(RenderContextForm context); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public abstract IHtmlNode Render(RenderContextForm context); - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - if (context is RenderContextForm formContext) - { - return Render(formContext); - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// if (context is RenderContextForm formContext) +// { +// return Render(formContext); +// } - return null; - } - } -} +// return null; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs index e0d44c7d..60d18fd9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs @@ -1,165 +1,165 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemButton : ControlFormItem - { - /// - /// Returns or sets the color of the button. - /// - public PropertyColorButton Color - { - get => (PropertyColorButton)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); - } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the Outline property. - /// - public bool Outline { get; set; } - - /// - /// Returns or sets whether the button should take up the full width. - /// - public TypeBlockButton Block - { - get => (TypeBlockButton)GetProperty(TypeBlockButton.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets whether the button is disabled. - /// - public bool Disabled { get; set; } - - /// - /// Returns or sets the content. - /// - public List Content { get; private set; } = new List(); - - /// - /// Event is triggered when the button is clicked. - /// - public EventHandler Click; - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the type. (button, submit, reset) - /// - public TypeButton Type { get; set; } = TypeButton.Default; - - /// - /// Returns or sets the value. - /// - public string Value { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemButton(string id = null) - : base(id) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - Disabled = false; - Size = TypeSizeButton.Default; - - if (context.Request.HasParameter(Name)) - { - var value = context.Request.GetParameter(Name)?.Value; - - if (!string.IsNullOrWhiteSpace(Value) && value == Value) - { - OnClickEvent(new FormEventArgs() { Context = context }); - } - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var html = new HtmlElementFieldButton() - { - Id = Id, - Name = Name, - Type = Type.ToTypeString(), - Value = Value, - Class = Css.Concatenate("btn", GetClasses()), - Style = GetStyles(), - Role = Role, - Disabled = Disabled, - OnClick = OnClick?.ToString() - }; - - if (Icon != null && Icon.HasIcon) - { - html.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - html.Elements.Add(new HtmlText(I18N(context.Culture, Text))); - } - - if (Content.Count > 0) - { - html.Elements.AddRange(Content.Select(x => x.Render(context))); - } - - return html; - } - - /// - /// Triggers the click event. - /// - /// The event argument. - protected virtual void OnClickEvent(FormEventArgs e) - { - Click?.Invoke(this, e); - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemButton : ControlFormItem +// { +// /// +// /// Returns or sets the color of the button. +// /// +// public PropertyColorButton Color +// { +// get => (PropertyColorButton)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); +// } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeButton Size +// { +// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the Outline property. +// /// +// public bool Outline { get; set; } + +// /// +// /// Returns or sets whether the button should take up the full width. +// /// +// public TypeBlockButton Block +// { +// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets whether the button is disabled. +// /// +// public bool Disabled { get; set; } + +// /// +// /// Returns or sets the content. +// /// +// public List Content { get; private set; } = new List(); + +// /// +// /// Event is triggered when the button is clicked. +// /// +// public EventHandler Click; + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the type. (button, submit, reset) +// /// +// public TypeButton Type { get; set; } = TypeButton.Default; + +// /// +// /// Returns or sets the value. +// /// +// public string Value { get; set; } + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemButton(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// Disabled = false; +// Size = TypeSizeButton.Default; + +// if (context.Request.HasParameter(Name)) +// { +// var value = context.Request.GetParameter(Name)?.Value; + +// if (!string.IsNullOrWhiteSpace(Value) && value == Value) +// { +// OnClickEvent(new FormEventArgs() { Context = context }); +// } +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var html = new HtmlElementFieldButton() +// { +// Id = Id, +// Name = Name, +// Type = Type.ToTypeString(), +// Value = Value, +// Class = Css.Concatenate("btn", GetClasses()), +// Style = GetStyles(), +// Role = Role, +// Disabled = Disabled, +// OnClick = OnClick?.ToString() +// }; + +// if (Icon != null && Icon.HasIcon) +// { +// html.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); +// } + +// if (Content.Count > 0) +// { +// html.Elements.AddRange(Content.Select(x => x.Render(context))); +// } + +// return html; +// } + +// /// +// /// Triggers the click event. +// /// +// /// The event argument. +// protected virtual void OnClickEvent(FormEventArgs e) +// { +// Click?.Invoke(this, e); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs index f29aa7e4..b1f767a0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs @@ -1,23 +1,23 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; +ο»Ώ//using WebExpress.WebCore.Internationalization; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemButtonSubmit : ControlFormItemButton - { - /// - /// Initializes a new instance of the class. - /// - /// The control id. - public ControlFormItemButtonSubmit(string id) - : base(id) - { - Name = Id; - Text = InternationalizationManager.I18N("webexpress.webui", "form.submit.label"); - Icon = new PropertyIcon(TypeIcon.Save); - Color = new PropertyColorButton(TypeColorButton.Success); - Type = TypeButton.Submit; - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); - OnClick = new PropertyOnClick($"$('#{Id}').val('submit');"); - } - } -} +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemButtonSubmit : ControlFormItemButton +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The control id. +// public ControlFormItemButtonSubmit(string id) +// : base(id) +// { +// Name = Id; +// Text = I18N.Translate("webexpress.webui", "form.submit.label"); +// Icon = new PropertyIcon(TypeIcon.Save); +// Color = new PropertyColorButton(TypeColorButton.Success); +// Type = TypeButton.Submit; +// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); +// OnClick = new PropertyOnClick($"$('#{Id}').val('submit');"); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs index 4d68c1b8..6277f687 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs @@ -1,114 +1,114 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation - { - /// - /// Returns or sets the form items. - /// - public ICollection Items { get; } = new List(); +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation +// { +// /// +// /// Returns or sets the form items. +// /// +// public ICollection Items { get; } = new List(); - /// - /// Determines whether the inputs are valid. - /// - public ICollection ValidationResults { get; } = new List(); +// /// +// /// Determines whether the inputs are valid. +// /// +// public ICollection ValidationResults { get; } = new List(); - /// - /// Returns or sets whether the form element has been validated. - /// - private bool IsValidated { get; set; } +// /// +// /// Returns or sets whether the form element has been validated. +// /// +// private bool IsValidated { get; set; } - /// - /// Returns the most serious validation result. - /// - public virtual TypesInputValidity ValidationResult - { - get - { - var buf = ValidationResults; +// /// +// /// Returns the most serious validation result. +// /// +// public virtual TypesInputValidity ValidationResult +// { +// get +// { +// var buf = ValidationResults; - if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - return TypesInputValidity.Error; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) - { - return TypesInputValidity.Warning; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) - { - return TypesInputValidity.Success; - } +// if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) +// { +// return TypesInputValidity.Error; +// } +// else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) +// { +// return TypesInputValidity.Warning; +// } +// else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) +// { +// return TypesInputValidity.Success; +// } - return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; - } - } +// return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; +// } +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroup(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroup(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form item. - public ControlFormItemGroup(string id, params ControlFormItem[] item) - : base(id) - { - (Items as List).AddRange(item); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form item. +// public ControlFormItemGroup(string id, params ControlFormItem[] item) +// : base(id) +// { +// (Items as List).AddRange(item); +// } - /// - /// Initializes a new instance of the class. - /// - ///The form item. - public ControlFormItemGroup(params ControlFormItem[] item) - : base(null) - { - (Items as List).AddRange(item); - } +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form item. +// public ControlFormItemGroup(params ControlFormItem[] item) +// : base(null) +// { +// (Items as List).AddRange(item); +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var groupContex = new RenderContextFormGroup(context, this); +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var groupContex = new RenderContextFormGroup(context, this); - foreach (var item in Items) - { - item.Initialize(groupContex); - } - } +// foreach (var item in Items) +// { +// item.Initialize(groupContex); +// } +// } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public virtual void Validate(RenderContextForm context) - { - var validationResults = ValidationResults as List; +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public virtual void Validate(RenderContextForm context) +// { +// var validationResults = ValidationResults as List; - validationResults.Clear(); +// validationResults.Clear(); - foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) - { - v.Validate(context); +// foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) +// { +// v.Validate(context); - validationResults.AddRange(v.ValidationResults); - } - } - } -} +// validationResults.AddRange(v.ValidationResults); +// } +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs index d83ed0ce..335b5a34 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs @@ -1,129 +1,129 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupColumn : ControlFormItemGroup - { - /// - /// Returns the percentage distribution of the columns. - /// - public ICollection Distribution { get; set; } = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupColumn(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupColumn(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupColumn(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-horizontal", GetClasses()), - Style = GetStyles(), - }; - - var body = new HtmlElementTextContentDiv() { }; - - foreach (var item in Items) - { - var row = new HtmlElementTextContentDiv() { }; - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - label.Classes.Add("me-2"); - help.Text = context.I18N(input?.Help); - help.Classes.Add("ms-2"); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - - row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); - } - - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); - - if (input != null) - { - row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); - } - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv()); - row.Elements.Add(item.Render(context)); - row.Elements.Add(new HtmlElementTextContentDiv()); - } - - body.Elements.Add(row); - } - - html.Elements.Add(body); - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupColumn : ControlFormItemGroup +// { +// /// +// /// Returns the percentage distribution of the columns. +// /// +// public ICollection Distribution { get; set; } = new List(); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupColumn(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupColumn(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupColumn(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-horizontal", GetClasses()), +// Style = GetStyles(), +// }; + +// var body = new HtmlElementTextContentDiv() { }; + +// foreach (var item in Items) +// { +// var row = new HtmlElementTextContentDiv() { }; + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// label.Classes.Add("me-2"); +// help.Text = I18N.Translate(input?.Help); +// help.Classes.Add("ms-2"); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); + +// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); +// } + +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); + +// if (input != null) +// { +// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); +// } +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv()); +// row.Elements.Add(item.Render(context)); +// row.Elements.Add(new HtmlElementTextContentDiv()); +// } + +// body.Elements.Add(row); +// } + +// html.Elements.Add(body); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs index b0171668..d4f72edc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs @@ -1,142 +1,142 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupColumnHorizontal : ControlFormItemGroupColumn - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupColumnHorizontal(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupColumnHorizontal(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-column-horizontal", GetClasses()), - Style = GetStyles(), - }; - - var max = 100; - var offset = 0; - - foreach (var item in Items) - { - var div = new HtmlElementTextContentDiv() { Style = "" }; - var width = -1; - - if (Distribution.Count > offset) - { - width = Distribution.Skip(offset).Take(1).FirstOrDefault(); - div.Style = $"width: {width}%"; - max -= width; - - offset++; - } - else if (Items.Count > offset) - { - width = max / (Items.Count - offset); - div.Style = $"width: {width}%"; - } - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - var row = new HtmlElementTextContentDiv() { Class = "" }; - var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; - var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - help.Text = context.I18N(input?.Help); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) - { - Style = "display: flex;" - }); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); - } - - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); - - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); - } - - div.Elements.Add(table); - } - else - { - div.Elements.Add(item.Render(renderContext)); - } - - html.Elements.Add(div); - } - - return html; - } - } -} +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupColumnHorizontal : ControlFormItemGroupColumn +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupColumnHorizontal(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupColumnHorizontal(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-column-horizontal", GetClasses()), +// Style = GetStyles(), +// }; + +// var max = 100; +// var offset = 0; + +// foreach (var item in Items) +// { +// var div = new HtmlElementTextContentDiv() { Style = "" }; +// var width = -1; + +// if (Distribution.Count > offset) +// { +// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); +// div.Style = $"width: {width}%"; +// max -= width; + +// offset++; +// } +// else if (Items.Count > offset) +// { +// width = max / (Items.Count - offset); +// div.Style = $"width: {width}%"; +// } + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); +// //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; +// var row = new HtmlElementTextContentDiv() { Class = "" }; +// var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; +// var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// help.Text = I18N.Translate(input?.Help); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); +// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) +// { +// Style = "display: flex;" +// }); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); +// } + +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); + +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); +// } + +// div.Elements.Add(table); +// } +// else +// { +// div.Elements.Add(item.Render(renderContext)); +// } + +// html.Elements.Add(div); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs index e527a3f2..3b0e86cb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs @@ -1,144 +1,144 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupColumnMix : ControlFormItemGroupColumn - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupColumnMix(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupColumnMix(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupColumnMix(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-column-mix", GetClasses()), - Style = GetStyles(), - }; - - var max = 100; - var offset = 0; - - foreach (var item in Items) - { - var div = new HtmlElementTextContentDiv() { Style = "" }; - var width = -1; - - if (Distribution.Count > offset) - { - width = Distribution.Skip(offset).Take(1).FirstOrDefault(); - div.Style = $"width: {width}%"; - max -= width; - - offset++; - } - else if (Items.Count > offset) - { - width = max / (Items.Count - offset); - div.Style = $"width: {width}%"; - } - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - var row = new HtmlElementTextContentDiv() { Class = "" }; - var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; - var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - help.Text = context.I18N(input?.Help); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) - { - Style = "display: flex;" - }); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); - } - - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); - } - - div.Elements.Add(table); - } - else - { - div.Elements.Add(item.Render(context)); - } - - html.Elements.Add(div); - } - - return html; - } - } -} +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupColumnMix : ControlFormItemGroupColumn +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupColumnMix(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupColumnMix(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupColumnMix(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-column-mix", GetClasses()), +// Style = GetStyles(), +// }; + +// var max = 100; +// var offset = 0; + +// foreach (var item in Items) +// { +// var div = new HtmlElementTextContentDiv() { Style = "" }; +// var width = -1; + +// if (Distribution.Count > offset) +// { +// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); +// div.Style = $"width: {width}%"; +// max -= width; + +// offset++; +// } +// else if (Items.Count > offset) +// { +// width = max / (Items.Count - offset); +// div.Style = $"width: {width}%"; +// } + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); +// //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; +// var row = new HtmlElementTextContentDiv() { Class = "" }; +// var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; +// var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// help.Text = I18N.Translate(input?.Help); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); +// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) +// { +// Style = "display: flex;" +// }); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); +// } + +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); +// } + +// div.Elements.Add(table); +// } +// else +// { +// div.Elements.Add(item.Render(context)); +// } + +// html.Elements.Add(div); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs index 7a4f6a89..eaac72ec 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs @@ -1,139 +1,139 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupColumnVertical : ControlFormItemGroupColumn - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupColumnVertical(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupColumnVertical(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupColumnVertical(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-column", GetClasses()), - Style = GetStyles(), - }; - - var max = 100; - var offset = 0; - - foreach (var item in Items) - { - var div = new HtmlElementTextContentDiv() { Style = "" }; - var width = -1; - - if (Distribution.Count > offset) - { - width = Distribution.Skip(offset).Take(1).FirstOrDefault(); - div.Style = $"width: {width}%"; - max = max - width; - - offset++; - } - else if (Items.Count > offset) - { - width = max / (Items.Count - offset); - div.Style = $"width: {width}%"; - } - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - help.Text = context.I18N(input?.Help); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) - { - Style = "display: flex;" - }); - } - else - { - fieldset.Elements.Add(label.Render(renderContext)); - } - - fieldset.Elements.Add(item.Render(renderContext)); - - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - fieldset.Elements.Add(help.Render(renderContext)); - } - - div.Elements.Add(fieldset); - } - else - { - div.Elements.Add(item.Render(context)); - } - - html.Elements.Add(div); - } - - return html; - } - } -} +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupColumnVertical : ControlFormItemGroupColumn +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupColumnVertical(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupColumnVertical(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupColumnVertical(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-column", GetClasses()), +// Style = GetStyles(), +// }; + +// var max = 100; +// var offset = 0; + +// foreach (var item in Items) +// { +// var div = new HtmlElementTextContentDiv() { Style = "" }; +// var width = -1; + +// if (Distribution.Count > offset) +// { +// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); +// div.Style = $"width: {width}%"; +// max = max - width; + +// offset++; +// } +// else if (Items.Count > offset) +// { +// width = max / (Items.Count - offset); +// div.Style = $"width: {width}%"; +// } + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); +// var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// help.Text = I18N.Translate(input?.Help); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); +// fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) +// { +// Style = "display: flex;" +// }); +// } +// else +// { +// fieldset.Elements.Add(label.Render(renderContext)); +// } + +// fieldset.Elements.Add(item.Render(renderContext)); + +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// fieldset.Elements.Add(help.Render(renderContext)); +// } + +// div.Elements.Add(fieldset); +// } +// else +// { +// div.Elements.Add(item.Render(context)); +// } + +// html.Elements.Add(div); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs index 60b9f3d3..4db37df7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs @@ -1,123 +1,123 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupHorizontal : ControlFormItemGroup - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupHorizontal(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupHorizontal(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupHorizontal(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-horizontal", GetClasses()), - Style = GetStyles(), - }; - - var body = new HtmlElementTextContentDiv() { }; - - foreach (var item in Items) - { - var row = new HtmlElementTextContentDiv() { }; - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - label.Classes.Add("me-2"); - help.Text = context.I18N(input?.Help); - help.Classes.Add("ms-2"); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - - row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext)) { }); - } - - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); - - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); - } - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv()); - row.Elements.Add(item.Render(context)); - row.Elements.Add(new HtmlElementTextContentDiv()); - } - - body.Elements.Add(row); - } - - html.Elements.Add(body); - - return html; - } - } -} +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupHorizontal : ControlFormItemGroup +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupHorizontal(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupHorizontal(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupHorizontal(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-horizontal", GetClasses()), +// Style = GetStyles(), +// }; + +// var body = new HtmlElementTextContentDiv() { }; + +// foreach (var item in Items) +// { +// var row = new HtmlElementTextContentDiv() { }; + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// label.Classes.Add("me-2"); +// help.Text = I18N.Translate(input?.Help); +// help.Classes.Add("ms-2"); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); + +// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext)) { }); +// } + +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); + +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); +// } +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv()); +// row.Elements.Add(item.Render(context)); +// row.Elements.Add(new HtmlElementTextContentDiv()); +// } + +// body.Elements.Add(row); +// } + +// html.Elements.Add(body); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs index 5076ca60..ec46804b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs @@ -1,124 +1,124 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupMix : ControlFormItemGroup - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupMix(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupMix(string id, params ControlFormItem[] items) - : base(id, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupMix(params ControlFormItem[] items) - : base(null, items) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); - - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("form-group-mix", GetClasses()), - Style = GetStyles(), - }; - - var body = new HtmlElementTextContentDiv() { }; - - foreach (var item in Items) - { - var row = new HtmlElementTextContentDiv() { }; - - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - - label.Initialize(renderContext); - help.Initialize(renderContext); - - label.Text = context.I18N(input?.Label); - label.FormItem = item; - label.Classes.Add("me-2"); - help.Text = context.I18N(input?.Help); - - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - - row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext))); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); - } - - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); - } - } - else - { - row.Elements.Add(new HtmlElementTextContentDiv()); - row.Elements.Add(item.Render(context)); - row.Elements.Add(new HtmlElementTextContentDiv()); - } - - body.Elements.Add(row); - } - - html.Elements.Add(body); - - return html; - } - } -} +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupMix : ControlFormItemGroup +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupMix(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupMix(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupMix(params ControlFormItem[] items) +// : base(null, items) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); + +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("form-group-mix", GetClasses()), +// Style = GetStyles(), +// }; + +// var body = new HtmlElementTextContentDiv() { }; + +// foreach (var item in Items) +// { +// var row = new HtmlElementTextContentDiv() { }; + +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + +// label.Initialize(renderContext); +// help.Initialize(renderContext); + +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// label.Classes.Add("me-2"); +// help.Text = I18N.Translate(input?.Help); + +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); + +// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext))); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); +// } + +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); +// } +// } +// else +// { +// row.Elements.Add(new HtmlElementTextContentDiv()); +// row.Elements.Add(item.Render(context)); +// row.Elements.Add(new HtmlElementTextContentDiv()); +// } + +// body.Elements.Add(row); +// } + +// html.Elements.Add(body); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs index 2c5dd6e1..1e7948d0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs @@ -1,116 +1,116 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grouping of controls. - /// - public class ControlFormItemGroupVertical : ControlFormItemGroup - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemGroupVertical(string id = null) - : base(id) - { - } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grouping of controls. +// /// +// public class ControlFormItemGroupVertical : ControlFormItemGroup +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemGroupVertical(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - ///The form controls. - public ControlFormItemGroupVertical(string id, params ControlFormItem[] items) - : base(id, items) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// ///The form controls. +// public ControlFormItemGroupVertical(string id, params ControlFormItem[] items) +// : base(id, items) +// { +// } - /// - /// Initializes a new instance of the class. - /// - ///The form controls. - public ControlFormItemGroupVertical(params ControlFormItem[] items) - : base(null, items) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// ///The form controls. +// public ControlFormItemGroupVertical(params ControlFormItem[] items) +// : base(null, items) +// { +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var grpupContex = new RenderContextFormGroup(context, this); +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var grpupContex = new RenderContextFormGroup(context, this); - foreach (var item in Items) - { - item.Initialize(grpupContex); - } - } +// foreach (var item in Items) +// { +// item.Initialize(grpupContex); +// } +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var renderContext = new RenderContextFormGroup(context, this); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var renderContext = new RenderContextFormGroup(context, this); - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - }; +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// }; - foreach (var item in Items) - { - if (item is ControlFormItemInput input) - { - var icon = new ControlIcon() { Icon = input?.Icon }; - var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); - var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; +// foreach (var item in Items) +// { +// if (item is ControlFormItemInput input) +// { +// var icon = new ControlIcon() { Icon = input?.Icon }; +// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); +// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); +// var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - label.Initialize(renderContext); - help.Initialize(renderContext); +// label.Initialize(renderContext); +// help.Initialize(renderContext); - label.Text = context.I18N(input?.Label); - label.FormItem = item; - help.Text = context.I18N(input?.Help); +// label.Text = I18N.Translate(input?.Label); +// label.FormItem = item; +// help.Text = I18N.Translate(input?.Help); - if (icon.Icon != null) - { - icon.Classes.Add("me-2 pt-1"); - fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) - { - Style = "display: flex;" - }); - } - else - { - fieldset.Elements.Add(label.Render(renderContext)); - } +// if (icon.Icon != null) +// { +// icon.Classes.Add("me-2 pt-1"); +// fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) +// { +// Style = "display: flex;" +// }); +// } +// else +// { +// fieldset.Elements.Add(label.Render(renderContext)); +// } - fieldset.Elements.Add(item.Render(renderContext)); +// fieldset.Elements.Add(item.Render(renderContext)); - if (!string.IsNullOrWhiteSpace(input?.Help)) - { - fieldset.Elements.Add(help.Render(renderContext)); - } +// if (!string.IsNullOrWhiteSpace(input?.Help)) +// { +// fieldset.Elements.Add(help.Render(renderContext)); +// } - html.Elements.Add(fieldset); - } - else - { - html.Elements.Add(item?.Render(context)); - } - } +// html.Elements.Add(fieldset); +// } +// else +// { +// html.Elements.Add(item?.Render(context)); +// } +// } - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs index 3b599df4..4129a78c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs @@ -1,67 +1,67 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemHelpText : ControlFormItem - { - /// - /// Returns or sets the size of the text. - /// - public PropertySizeText Size - { - get => (PropertySizeText)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemHelpText : ControlFormItem +// { +// /// +// /// Returns or sets the size of the text. +// /// +// public PropertySizeText Size +// { +// get => (PropertySizeText)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); +// } - /// - /// Returns or sets the help text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the help text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemHelpText(string id) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemHelpText(string id) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlFormItemHelpText(string id, string text) - : this(id) - { - Text = text; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlFormItemHelpText(string id, string text) +// : this(id) +// { +// Text = text; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - TextColor = new PropertyColorText(TypeColorText.Muted); - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// TextColor = new PropertyColorText(TypeColorText.Muted); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - return new HtmlElementTextSemanticsSmall() - { - Text = I18N(context.Culture, Text), - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// return new HtmlElementTextSemanticsSmall() +// { +// Text = I18N.Translate(context.Culture, Text), +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs index 7156f4cb..11821782 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs @@ -1,152 +1,152 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Identifies a control that is to be filled in by the user. - /// - public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation - { - /// - /// Event to validate the input values. - /// - public event EventHandler Validation; - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the label. - /// - public string Label { get; set; } - - /// - /// Returns or sets an optional help text. - /// - public string Help { get; set; } - - /// - /// Returns or sets whether the input element is disabled. - /// - public bool Disabled { get; set; } - - /// - /// Returns or sets the elements that are displayed in front of the control. - /// - public List Prepend { get; private set; } - - /// - /// Returns or sets the elements that are displayed after the control. - /// - public List Append { get; private set; } - - /// - /// Returns or sets whether the form element has been validated. - /// - private bool IsValidated { get; set; } - - /// - /// Returns or sets an object that is linked to the control. - /// - public object Tag { get; set; } - - /// - /// Determines whether the inputs are valid. - /// - public virtual ICollection ValidationResults { get; } = new List(); - - /// - /// Returns the most serious validation result. - /// - public virtual TypesInputValidity ValidationResult - { - get - { - var buf = ValidationResults; - - if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - return TypesInputValidity.Error; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) - { - return TypesInputValidity.Warning; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) - { - return TypesInputValidity.Success; - } - - return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; - } - } - - /// - /// Returns or sets the value. - /// - public virtual string Value { get; set; } = string.Empty; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInput(string id) - : base(id) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Prepend = new List(); - Append = new List(); - IsValidated = false; - } - - /// - /// Initializes the form.emement - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - } - - /// - /// Raises the validation event. - /// - /// The event argument. - protected virtual void OnValidation(ValidationEventArgs e) - { - Validation?.Invoke(this, e); - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public virtual void Validate(RenderContextForm context) - { - IsValidated = true; - - if (ValidationResults is List validationResults) - { - validationResults.Clear(); - - if (!Disabled) - { - var args = new ValidationEventArgs() { Value = Value, Context = context }; - OnValidation(args); - - validationResults.AddRange(args.Results); - } - } - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Identifies a control that is to be filled in by the user. +// /// +// public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation +// { +// /// +// /// Event to validate the input values. +// /// +// public event EventHandler Validation; + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Returns or sets the label. +// /// +// public string Label { get; set; } + +// /// +// /// Returns or sets an optional help text. +// /// +// public string Help { get; set; } + +// /// +// /// Returns or sets whether the input element is disabled. +// /// +// public bool Disabled { get; set; } + +// /// +// /// Returns or sets the elements that are displayed in front of the control. +// /// +// public List Prepend { get; private set; } + +// /// +// /// Returns or sets the elements that are displayed after the control. +// /// +// public List Append { get; private set; } + +// /// +// /// Returns or sets whether the form element has been validated. +// /// +// private bool IsValidated { get; set; } + +// /// +// /// Returns or sets an object that is linked to the control. +// /// +// public object Tag { get; set; } + +// /// +// /// Determines whether the inputs are valid. +// /// +// public virtual ICollection ValidationResults { get; } = new List(); + +// /// +// /// Returns the most serious validation result. +// /// +// public virtual TypesInputValidity ValidationResult +// { +// get +// { +// var buf = ValidationResults; + +// if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) +// { +// return TypesInputValidity.Error; +// } +// else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) +// { +// return TypesInputValidity.Warning; +// } +// else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) +// { +// return TypesInputValidity.Success; +// } + +// return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; +// } +// } + +// /// +// /// Returns or sets the value. +// /// +// public virtual string Value { get; set; } = string.Empty; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInput(string id) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Prepend = new List(); +// Append = new List(); +// IsValidated = false; +// } + +// /// +// /// Initializes the form.emement +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// } + +// /// +// /// Raises the validation event. +// /// +// /// The event argument. +// protected virtual void OnValidation(ValidationEventArgs e) +// { +// Validation?.Invoke(this, e); +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public virtual void Validate(RenderContextForm context) +// { +// IsValidated = true; + +// if (ValidationResults is List validationResults) +// { +// validationResults.Clear(); + +// if (!Disabled) +// { +// var args = new ValidationEventArgs() { Value = Value, Context = context }; +// OnValidation(args); + +// validationResults.AddRange(args.Results); +// } +// } +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs index 5bea4d55..1fe31463 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs @@ -1,87 +1,87 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.Internationalization; +ο»Ώ//using System; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.Internationalization; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputCheckbox : ControlFormItemInput - { - /// - /// Returns or sets whether the checkbox should be displayed on a new line. - /// - public bool Inline { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputCheckbox : ControlFormItemInput +// { +// /// +// /// Returns or sets whether the checkbox should be displayed on a new line. +// /// +// public bool Inline { get; set; } - /// - /// Returns or sets the description. - /// - public string Description { get; set; } +// /// +// /// Returns or sets the description. +// /// +// public string Description { get; set; } - /// - /// Returns or sets a search pattern that checks the content. - /// - public string Pattern { get; set; } +// /// +// /// Returns or sets a search pattern that checks the content. +// /// +// public string Pattern { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id. - public ControlFormItemInputCheckbox(string id = null) - : base(id) - { - Value = "false"; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// public ControlFormItemInputCheckbox(string id = null) +// : base(id) +// { +// Value = "false"; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - var value = context.Request.GetParameter(Name)?.Value; +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// var value = context.Request.GetParameter(Name)?.Value; - Value = string.IsNullOrWhiteSpace(value) || !value.Equals("on", StringComparison.OrdinalIgnoreCase) ? "false" : "true"; - } +// Value = string.IsNullOrWhiteSpace(value) || !value.Equals("on", StringComparison.OrdinalIgnoreCase) ? "false" : "true"; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var html = new HtmlElementTextContentDiv - ( - new HtmlElementFieldLabel - ( - new HtmlElementFieldInput() - { - Name = Name, - Pattern = Pattern, - Type = "checkbox", - Disabled = Disabled, - //Role = Role, - Checked = Value.Equals("true") - }, - new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + context.I18N(Description)) - ) - { - } - ) - { - Class = Css.Concatenate("checkbox", GetClasses()), - Style = GetStyles(), - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var html = new HtmlElementTextContentDiv +// ( +// new HtmlElementFieldLabel +// ( +// new HtmlElementFieldInput() +// { +// Name = Name, +// Pattern = Pattern, +// Type = "checkbox", +// Disabled = Disabled, +// //Role = Role, +// Checked = Value.Equals("true") +// }, +// new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + I18N.Translate(Description)) +// ) +// { +// } +// ) +// { +// Class = Css.Concatenate("checkbox", GetClasses()), +// Style = GetStyles(), +// }; - return html; - } +// return html; +// } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - } -} +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs index cb355baa..ad0dcc49 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs @@ -1,128 +1,128 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputComboBox : ControlFormItemInput - { - /// - /// Returns or sets the entries. - /// - public List Items { get; private set; } = new List(); +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputComboBox : ControlFormItemInput +// { +// /// +// /// Returns or sets the entries. +// /// +// public List Items { get; private set; } = new List(); - ///// - ///// Returns or sets the selected item. - ///// - //public string Selected { get; set; } +// ///// +// ///// Returns or sets the selected item. +// ///// +// //public string Selected { get; set; } - /// - /// Returns or sets the OnChange attribute. - /// - public PropertyOnChange OnChange { get; set; } +// /// +// /// Returns or sets the OnChange attribute. +// /// +// public PropertyOnChange OnChange { get; set; } - ///// - ///// Returns or sets the selected item. anhand des Wertes - ///// - //public string SelectedValue { get; set; } +// ///// +// ///// Returns or sets the selected item. anhand des Wertes +// ///// +// //public string SelectedValue { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputComboBox(string id = null) - : base(id) - { - Name = id; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputComboBox(string id = null) +// : base(id) +// { +// Name = id; +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The ComboBox entries. - public ControlFormItemInputComboBox(string id, params string[] items) - : this(id) - { - Items.AddRange(from v in items select new ControlFormItemInputComboBoxItem() { Text = v }); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The ComboBox entries. +// public ControlFormItemInputComboBox(string id, params string[] items) +// : this(id) +// { +// Items.AddRange(from v in items select new ControlFormItemInputComboBoxItem() { Text = v }); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The ComboBox entries. - public ControlFormItemInputComboBox(string id, params ControlFormItemInputComboBoxItem[] items) - : this(id) - { - Items.AddRange(items); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The ComboBox entries. +// public ControlFormItemInputComboBox(string id, params ControlFormItemInputComboBoxItem[] items) +// : this(id) +// { +// Items.AddRange(items); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The ComboBox entries. - public ControlFormItemInputComboBox(string id, string name, IEnumerable items) - : this(id, name) - { - Items.AddRange(items); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The ComboBox entries. +// public ControlFormItemInputComboBox(string id, string name, IEnumerable items) +// : this(id, name) +// { +// Items.AddRange(items); +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - Value = context.Request.GetParameter(Name)?.Value; - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// Value = context.Request.GetParameter(Name)?.Value; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var html = new HtmlElementFieldSelect() - { - Id = Id, - Name = Name, - Class = Css.Concatenate("form-select", GetClasses()), - Style = GetStyles(), - Role = Role, - Disabled = Disabled, - OnChange = OnChange?.ToString() - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var html = new HtmlElementFieldSelect() +// { +// Id = Id, +// Name = Name, +// Class = Css.Concatenate("form-select", GetClasses()), +// Style = GetStyles(), +// Role = Role, +// Disabled = Disabled, +// OnChange = OnChange?.ToString() +// }; - foreach (var v in Items) - { - if (v.SubItems.Count > 0) - { - html.Elements.Add(new HtmlElementFormOptgroup() { Label = v.Text }); - foreach (var s in v.SubItems) - { - html.Elements.Add(new HtmlElementFormOption() { Value = s.Value, Text = I18N(context.Culture, s.Text), Selected = (s.Value == Value) }); - } - } - else - { - html.Elements.Add(new HtmlElementFormOption() { Value = v.Value, Text = I18N(context.Culture, v.Text), Selected = (v.Value == Value) }); - } - } +// foreach (var v in Items) +// { +// if (v.SubItems.Count > 0) +// { +// html.Elements.Add(new HtmlElementFormOptgroup() { Label = v.Text }); +// foreach (var s in v.SubItems) +// { +// html.Elements.Add(new HtmlElementFormOption() { Value = s.Value, Text = I18N.Translate(context.Culture, s.Text), Selected = (s.Value == Value) }); +// } +// } +// else +// { +// html.Elements.Add(new HtmlElementFormOption() { Value = v.Value, Text = I18N.Translate(context.Culture, v.Text), Selected = (v.Value == Value) }); +// } +// } - return html; - } +// return html; +// } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - } -} +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs index 8cc41d0e..8b3903d3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs @@ -1,52 +1,52 @@ -ο»Ώusing System.Collections.Generic; +ο»Ώ//using System.Collections.Generic; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputComboBoxItem - { - public List SubItems { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputComboBoxItem +// { +// public List SubItems { get; private set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Returns or sets a value. - /// - public string Value { get; set; } +// /// +// /// Returns or sets a value. +// /// +// public string Value { get; set; } - /// - /// Returns or sets a tag value. - /// - public object Tag { get; set; } +// /// +// /// Returns or sets a tag value. +// /// +// public object Tag { get; set; } - /// - /// Initializes a new instance of the class. - /// - public ControlFormItemInputComboBoxItem() - { - SubItems = new List(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// public ControlFormItemInputComboBoxItem() +// { +// SubItems = new List(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The child entries. - public ControlFormItemInputComboBoxItem(params ControlFormItemInputComboBoxItem[] subitems) - : this() - { - SubItems.AddRange(subitems); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The child entries. +// public ControlFormItemInputComboBoxItem(params ControlFormItemInputComboBoxItem[] subitems) +// : this() +// { +// SubItems.AddRange(subitems); +// } - /// - /// Initializes a new instance of the class. - /// - /// The child entries. - public ControlFormItemInputComboBoxItem(IEnumerable subitems) - : this() - { - SubItems.AddRange(subitems); - } - } -} +// /// +// /// Initializes a new instance of the class. +// /// +// /// The child entries. +// public ControlFormItemInputComboBoxItem(IEnumerable subitems) +// : this() +// { +// SubItems.AddRange(subitems); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs index 1c8d1955..25fd19c1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs @@ -1,132 +1,129 @@ -ο»Ώusing WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebUri; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputDatepicker : ControlFormItemInput - { - /// - /// Determines whether the control is automatically initialized. - /// - public bool AutoInitialize { get; set; } - - /// - /// Returns or sets the description. - /// - public string Description { get; set; } - - /// - /// Returns or sets the minimum length. - /// - public string MinLength { get; set; } - - /// - /// Returns or sets the maximum length. - /// - public string MaxLength { get; set; } - - /// - /// Returns or sets whether inputs are enforced. - /// - public bool Required { get; set; } - - /// - /// Returns or sets a search pattern that checks the content. - /// - public string Pattern { get; set; } - - ///// - ///// Returns the initialization code (JQuerry). - ///// - //public string InitializeCode => "$('#" + Id + " input').datepicker({ startDate: -3 });"; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputDatepicker(string id = null) - : base(!string.IsNullOrWhiteSpace(id) ? id : "datepicker") - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - AutoInitialize = true; - - Value = context?.Request.GetParameter(Name)?.Value; - - var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module)); - if (module != null) - { - context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(module.ContextPath, "/assets/js/bootstrap-datepicker.min.js")); - context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(module.ContextPath, "/assets/js/locales_datepicker/bootstrap-datepicker." + context.Culture.TwoLetterISOLanguageName.ToLower() + ".min.js")); - context.VisualTree.CssLinks.Add(UriResource.Combine(module.ContextPath, "/assets/css/bootstrap-datepicker3.min.css")); - } - - context.AddScript(Id, @"$('#" + Id + @"').datepicker({format: ""dd.mm.yyyy"", todayBtn: true, language: ""de"", zIndexOffset: 999});"); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - - - //if (Disabled) - //{ - // Classes.Add("disabled"); - //} - - //if (AutoInitialize) - //{ - // context.Page.AddScript(Id, InitializeCode); - // AutoInitialize = false; - //} - - var input = new HtmlElementFieldInput() - { - Id = Id, - Name = Name, - Type = "text", - Class = "form-control", - Value = Value - }; - - //var span = new HtmlElementTextSemanticsSpan() - //{ - // Class = TypeIcon.Calendar.ToClass() - //}; - - //var div = new HtmlElementTextContentDiv(span) - //{ - // Class = "input-group-text" - //}; - - //var html = new HtmlElementTextContentDiv(input, div) - //{ - // Id = Id, - // Class = "input-group", - // //DataProvide = "datepicker" - //}; - - return input; - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - } -} +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebUri; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputDatepicker : ControlFormItemInput +// { +// /// +// /// Determines whether the control is automatically initialized. +// /// +// public bool AutoInitialize { get; set; } + +// /// +// /// Returns or sets the description. +// /// +// public string Description { get; set; } + +// /// +// /// Returns or sets the minimum length. +// /// +// public string MinLength { get; set; } + +// /// +// /// Returns or sets the maximum length. +// /// +// public string MaxLength { get; set; } + +// /// +// /// Returns or sets whether inputs are enforced. +// /// +// public bool Required { get; set; } + +// /// +// /// Returns or sets a search pattern that checks the content. +// /// +// public string Pattern { get; set; } + +// ///// +// ///// Returns the initialization code (JQuerry). +// ///// +// //public string InitializeCode => "$('#" + Id + " input').datepicker({ startDate: -3 });"; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputDatepicker(string id = null) +// : base(!string.IsNullOrWhiteSpace(id) ? id : "datepicker") +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// AutoInitialize = true; + +// var contextPath = context.PageContext?.ApplicationContext?.ContextPath; + +// Value = context?.Request.GetParameter(Name)?.Value; + +// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap-datepicker.min.js")); +// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/locales_datepicker/bootstrap-datepicker." + context.Culture.TwoLetterISOLanguageName.ToLower() + ".min.js")); +// context.VisualTree.CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap-datepicker3.min.css")); + +// context.AddScript(Id, @"$('#" + Id + @"').datepicker({format: ""dd.mm.yyyy"", todayBtn: true, language: ""de"", zIndexOffset: 999});"); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { + + +// //if (Disabled) +// //{ +// // Classes.Add("disabled"); +// //} + +// //if (AutoInitialize) +// //{ +// // context.Page.AddScript(Id, InitializeCode); +// // AutoInitialize = false; +// //} + +// var input = new HtmlElementFieldInput() +// { +// Id = Id, +// Name = Name, +// Type = "text", +// Class = "form-control", +// Value = Value +// }; + +// //var span = new HtmlElementTextSemanticsSpan() +// //{ +// // Class = TypeIcon.Calendar.ToClass() +// //}; + +// //var div = new HtmlElementTextContentDiv(span) +// //{ +// // Class = "input-group-text" +// //}; + +// //var html = new HtmlElementTextContentDiv(input, div) +// //{ +// // Id = Id, +// // Class = "input-group", +// // //DataProvide = "datepicker" +// //}; + +// return input; +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs index 20e1f3bc..3bfd7f26 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs @@ -1,114 +1,114 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputFile : ControlFormItemInput - { - /// - /// Returns or sets the description. - /// - public string Description { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputFile : ControlFormItemInput +// { +// /// +// /// Returns or sets the description. +// /// +// public string Description { get; set; } - /// - /// Returns or sets a placeholder text. - /// - public string Placeholder { get; set; } +// /// +// /// Returns or sets a placeholder text. +// /// +// public string Placeholder { get; set; } - /// - /// Returns or sets whether inputs are enforced. - /// - public bool Required { get; set; } +// /// +// /// Returns or sets whether inputs are enforced. +// /// +// public bool Required { get; set; } - /// - /// Returns or sets the accepted files. - /// - public ICollection AcceptFile { get; set; } = new List(); +// /// +// /// Returns or sets the accepted files. +// /// +// public ICollection AcceptFile { get; set; } = new List(); - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputFile(string id = null) - : base(!string.IsNullOrWhiteSpace(id) ? id : "file") - { - Name = Id; - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputFile(string id = null) +// : base(!string.IsNullOrWhiteSpace(id) ? id : "file") +// { +// Name = Id; +// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The name. - public ControlFormItemInputFile(string id, string name) - : base(!string.IsNullOrWhiteSpace(id) ? id : "file") - { - Name = name; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The name. +// public ControlFormItemInputFile(string id, string name) +// : base(!string.IsNullOrWhiteSpace(id) ? id : "file") +// { +// Name = name; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - Value = context?.Request.GetParameter(Name)?.Value; - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// Value = context?.Request.GetParameter(Name)?.Value; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - switch (ValidationResult) - { - case TypesInputValidity.Warning: - Classes.Add("input-warning"); - break; - case TypesInputValidity.Error: - Classes.Add("input-error"); - break; - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// switch (ValidationResult) +// { +// case TypesInputValidity.Warning: +// Classes.Add("input-warning"); +// break; +// case TypesInputValidity.Error: +// Classes.Add("input-error"); +// break; +// } - var html = new HtmlElementFieldInput() - { - Id = Id, - Value = Value, - Name = Name, - Type = "file", - Class = Css.Concatenate("form-control-file", GetClasses()), - Style = GetStyles(), - Role = Role, - Placeholder = Placeholder - }; +// var html = new HtmlElementFieldInput() +// { +// Id = Id, +// Value = Value, +// Name = Name, +// Type = "file", +// Class = Css.Concatenate("form-control-file", GetClasses()), +// Style = GetStyles(), +// Role = Role, +// Placeholder = Placeholder +// }; - html.AddUserAttribute("accept", string.Join(",", AcceptFile)); +// html.AddUserAttribute("accept", string.Join(",", AcceptFile)); - return html; - } +// return html; +// } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - if (Disabled) - { - return; - } +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// if (Disabled) +// { +// return; +// } - if (Required && string.IsNullOrWhiteSpace(base.Value)) - { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputfile.validation.required")); +// if (Required && string.IsNullOrWhiteSpace(base.Value)) +// { +// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputfile.validation.required")); - return; - } +// return; +// } - base.Validate(context); - } - } -} +// base.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs index 54fb5ccb..3e4e8e8d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs @@ -1,82 +1,82 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputGroup : ControlFormItemInput - { - /// - /// Returns or sets the group. - /// - public ControlFormItemGroup Group { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputGroup : ControlFormItemInput +// { +// /// +// /// Returns or sets the group. +// /// +// public ControlFormItemGroup Group { get; private set; } - /// - /// Determines whether the inputs are valid. - /// - public override ICollection ValidationResults => Group != null ? Group.ValidationResults : new List(); +// /// +// /// Determines whether the inputs are valid. +// /// +// public override ICollection ValidationResults => Group != null ? Group.ValidationResults : new List(); - /// - /// Returns the most serious validation result. - /// - public override TypesInputValidity ValidationResult => Group != null ? Group.ValidationResult : TypesInputValidity.Default; +// /// +// /// Returns the most serious validation result. +// /// +// public override TypesInputValidity ValidationResult => Group != null ? Group.ValidationResult : TypesInputValidity.Default; - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputGroup(string id = null) - : base(id) - { - Name = Id; - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputGroup(string id = null) +// : base(id) +// { +// Name = Id; +// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The name. - public ControlFormItemInputGroup(string id, ControlFormItemGroup group) - : base(id) - { - Name = id; - Group = group; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The name. +// public ControlFormItemInputGroup(string id, ControlFormItemGroup group) +// : base(id) +// { +// Name = id; +// Group = group; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - if (Group != null) - { - Group.Initialize(context); - } - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// if (Group != null) +// { +// Group.Initialize(context); +// } +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - return Group?.Render(context); - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// return Group?.Render(context); +// } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - if (Disabled) - { - return; - } +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// if (Disabled) +// { +// return; +// } - Group.Validate(context); - } - } -} +// Group.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs index aa058f16..fead0d92 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs @@ -1,54 +1,54 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; +ο»Ώ//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputHidden : ControlFormItemInput - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputHidden(string id = null) - : base(id) - { - Name = Id; - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputHidden : ControlFormItemInput +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputHidden(string id = null) +// : base(id) +// { +// Name = Id; +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The name. - public ControlFormItemInputHidden(string id, string name) - : base(id) - { - Name = name; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The name. +// public ControlFormItemInputHidden(string id, string name) +// : base(id) +// { +// Name = name; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - Value = context?.Request.GetParameter(Name)?.Value; - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// Value = context?.Request.GetParameter(Name)?.Value; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - return new HtmlElementFieldInput() - { - Id = Id, - Value = Value, - Name = Name, - Type = "hidden", - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// return new HtmlElementFieldInput() +// { +// Id = Id, +// Value = Value, +// Name = Name, +// Type = "hidden", +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs index 982a0aa7..6b918591 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs @@ -1,150 +1,150 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputMove : ControlFormItemInput - { - /// - /// Returns the entries. - /// - public ICollection Options { get; } = new List(); - - /// - /// Returns or sets the label of the selected options. - /// - public string SelectedHeader { get; set; } = "webexpress.webui:form.selectionmove.selected"; - - /// - /// Returns or sets the label. - /// - public string AvailableHeader { get; set; } = "webexpress.webui:form.selectionmove.available"; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputMove(string id = null) - : base(string.IsNullOrEmpty(id) ? typeof(ControlFormItemInputSelection).GUID.ToString() : id) - { - Name = Id; - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The entries. - public ControlFormItemInputMove(string id, params ControlFormItemInputSelectionItem[] items) - : this(id) - { - (Options as List).AddRange(items); - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - if (context.Request.HasParameter(Name)) - { - Value = context?.Request.GetParameter(Name)?.Value; - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var classes = Classes.ToList(); - - if (Disabled) - { - classes.Add("disabled"); - } - - switch (ValidationResult) - { - case TypesInputValidity.Warning: - classes.Add("input-warning"); - break; - case TypesInputValidity.Error: - classes.Add("input-error"); - break; - } - - var html = new HtmlElementTextContentDiv() - { - Id = $"selection-move-{Id}", - Style = GetStyles() - }; - - context.AddScript(Id, GetScript(context, $"selection-move-{Id}", string.Join(" ", classes))); - - return html; - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - - /// - /// Generates the javascript to control the control. - /// - /// The context in which the control is rendered. - /// The id of the control. - /// The css classes that are assigned to the control. - /// The javascript code. - protected virtual string GetScript(RenderContextForm context, string id, string css) - { - var settings = new - { - Id = id, - Name = Id, - CSS = css, - Header = new - { - Selected = context.I18N(SelectedHeader), - Available = context.I18N(AvailableHeader) - }, - Buttons = new - { - ToSelectedAll = context.I18N("Λ‚Λ‚"), - ToSelected = context.I18N("Λ‚"), - ToAvailableAll = context.I18N("ΛƒΛƒ"), - ToAvailable = context.I18N("Λƒ") - } - }; - - var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; - var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); - var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); - var valuesJson = JsonSerializer.Serialize(Value?.Split(";", System.StringSplitOptions.RemoveEmptyEntries), jsonOptions); - var builder = new StringBuilder(); - - builder.Append($"var options = {optionsJson};"); - builder.Append($"var settings = {settingsJson};"); - builder.Append($"var container = $('#{id}');"); - builder.Append($"var obj = new webexpress.webui.moveCtrl(settings);"); - builder.Append($"obj.options = options;"); - builder.Append($"obj.value = {(!string.IsNullOrWhiteSpace(valuesJson) ? valuesJson : "[]")};"); - builder.Append($"container.replaceWith(obj.getCtrl);"); - - return builder.ToString(); - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using System.Text; +//using System.Text.Json; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputMove : ControlFormItemInput +// { +// /// +// /// Returns the entries. +// /// +// public ICollection Options { get; } = new List(); + +// /// +// /// Returns or sets the label of the selected options. +// /// +// public string SelectedHeader { get; set; } = "webexpress.webui:form.selectionmove.selected"; + +// /// +// /// Returns or sets the label. +// /// +// public string AvailableHeader { get; set; } = "webexpress.webui:form.selectionmove.available"; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputMove(string id = null) +// : base(string.IsNullOrEmpty(id) ? typeof(ControlFormItemInputSelection).GUID.ToString() : id) +// { +// Name = Id; +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The entries. +// public ControlFormItemInputMove(string id, params ControlFormItemInputSelectionItem[] items) +// : this(id) +// { +// (Options as List).AddRange(items); +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// if (context.Request.HasParameter(Name)) +// { +// Value = context?.Request.GetParameter(Name)?.Value; +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var classes = Classes.ToList(); + +// if (Disabled) +// { +// classes.Add("disabled"); +// } + +// switch (ValidationResult) +// { +// case TypesInputValidity.Warning: +// classes.Add("input-warning"); +// break; +// case TypesInputValidity.Error: +// classes.Add("input-error"); +// break; +// } + +// var html = new HtmlElementTextContentDiv() +// { +// Id = $"selection-move-{Id}", +// Style = GetStyles() +// }; + +// context.AddScript(Id, GetScript(context, $"selection-move-{Id}", string.Join(" ", classes))); + +// return html; +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } + +// /// +// /// Generates the javascript to control the control. +// /// +// /// The context in which the control is rendered. +// /// The id of the control. +// /// The css classes that are assigned to the control. +// /// The javascript code. +// protected virtual string GetScript(RenderContextForm context, string id, string css) +// { +// var settings = new +// { +// Id = id, +// Name = Id, +// CSS = css, +// Header = new +// { +// Selected = I18N.Translate(SelectedHeader), +// Available = I18N.Translate(AvailableHeader) +// }, +// Buttons = new +// { +// ToSelectedAll = I18N.Translate("Λ‚Λ‚"), +// ToSelected = I18N.Translate("Λ‚"), +// ToAvailableAll = I18N.Translate("ΛƒΛƒ"), +// ToAvailable = I18N.Translate("Λƒ") +// } +// }; + +// var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; +// var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); +// var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); +// var valuesJson = JsonSerializer.Serialize(Value?.Split(";", System.StringSplitOptions.RemoveEmptyEntries), jsonOptions); +// var builder = new StringBuilder(); + +// builder.Append($"var options = {optionsJson};"); +// builder.Append($"var settings = {settingsJson};"); +// builder.Append($"var container = $('#{id}');"); +// builder.Append($"var obj = new webexpress.webui.moveCtrl(settings);"); +// builder.Append($"obj.options = options;"); +// builder.Append($"obj.value = {(!string.IsNullOrWhiteSpace(valuesJson) ? valuesJson : "[]")};"); +// builder.Append($"container.replaceWith(obj.getCtrl);"); + +// return builder.ToString(); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs index 21fbe7b2..63b04985 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs @@ -1,128 +1,128 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputRadio : ControlFormItemInput - { - /// - /// Returns or sets the value of the optiopn. - /// - public string Option { get; set; } - - /// - /// Liefert oder setzt ob die Checkbox in einer neuen Zeile angezeigt werden soll - /// - public bool Inline { get; set; } - - /// - /// Returns or sets the description. - /// - public string Description { get; set; } - - /// - /// Returns or sets a search pattern that checks the content. - /// - public string Pattern { get; set; } - - /// - /// Returns or sets whether the radio button is selected - /// - public bool Checked { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputRadio(string id = null) - : base(id) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The name. - public ControlFormItemInputRadio(string id, string name) - : this(id) - { - Name = name; - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - if (!string.IsNullOrWhiteSpace(Value)) - { - Checked = Value == Option; - } - - var c = new List - { - "radio" - }; - - if (Inline) - { - c.Add("form-check-inline"); - } - - if (Disabled) - { - c.Add("disabled"); - } - - var html = new HtmlElementTextContentDiv - ( - new HtmlElementFieldLabel - ( - new HtmlElementFieldInput() - { - Id = Id, - Name = Name, - Pattern = Pattern, - Type = "radio", - Disabled = Disabled, - Checked = Checked, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - Value = Option - }, - new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + Description) - ) - { - } - ) - { - Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))) - }; - - return html; - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputRadio : ControlFormItemInput +// { +// /// +// /// Returns or sets the value of the optiopn. +// /// +// public string Option { get; set; } + +// /// +// /// Liefert oder setzt ob die Checkbox in einer neuen Zeile angezeigt werden soll +// /// +// public bool Inline { get; set; } + +// /// +// /// Returns or sets the description. +// /// +// public string Description { get; set; } + +// /// +// /// Returns or sets a search pattern that checks the content. +// /// +// public string Pattern { get; set; } + +// /// +// /// Returns or sets whether the radio button is selected +// /// +// public bool Checked { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputRadio(string id = null) +// : base(id) +// { + +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The name. +// public ControlFormItemInputRadio(string id, string name) +// : this(id) +// { +// Name = name; +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// if (!string.IsNullOrWhiteSpace(Value)) +// { +// Checked = Value == Option; +// } + +// var c = new List +// { +// "radio" +// }; + +// if (Inline) +// { +// c.Add("form-check-inline"); +// } + +// if (Disabled) +// { +// c.Add("disabled"); +// } + +// var html = new HtmlElementTextContentDiv +// ( +// new HtmlElementFieldLabel +// ( +// new HtmlElementFieldInput() +// { +// Id = Id, +// Name = Name, +// Pattern = Pattern, +// Type = "radio", +// Disabled = Disabled, +// Checked = Checked, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// Value = Option +// }, +// new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + Description) +// ) +// { +// } +// ) +// { +// Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))) +// }; + +// return html; +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs index 96232fa0..737314a3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs @@ -1,161 +1,161 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.Json; -using WebExpress.WebCore.WebHtml; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputSelection : ControlFormItemInput - { - /// - /// Returns the entries. - /// - public ICollection Options { get; } = []; - - /// - /// Returns or sets the label of the selected options. - /// - public string Placeholder { get; set; } - - /// - /// Returns or sets whether to display the description of the option or hide it. - /// - public bool HideDescription { get; set; } - - /// - /// Allows you to select multiple items. - /// - public bool MultiSelect { get; set; } - - /// - /// Returns or sets the OnChange attribute. - /// - public PropertyOnChange OnChange { get; set; } - - /// - /// Returns or sets the value. - /// - public virtual ICollection Values => base.Value != null ? base.Value.Split(';', System.StringSplitOptions.RemoveEmptyEntries) : []; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputSelection(string id = null) - : base(id ?? Guid.NewGuid().ToString()) - { - Name = Id; - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The entries. - public ControlFormItemInputSelection(string id, params ControlFormItemInputSelectionItem[] items) - : this(id) - { - (Options as List).AddRange(items); - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - if (context.Request.HasParameter(Name)) - { - Value = context?.Request.GetParameter(Name)?.Value; - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var classes = Classes.ToList(); - - if (Disabled) - { - classes.Add("disabled"); - } - - switch (ValidationResult) - { - case TypesInputValidity.Warning: - classes.Add("input-warning"); - break; - case TypesInputValidity.Error: - classes.Add("input-error"); - break; - } - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Style = GetStyles() - }; - - context.AddScript(Id, GetScript(context, Id, string.Join(" ", classes))); - - return html; - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - } - - /// - /// Generates the javascript to control the control. - /// - /// The context in which the control is rendered. - /// The ID of the control. - /// The CSS classes that are assigned to the control. - /// The javascript code. - protected virtual string GetScript(RenderContextForm context, string id, string css) - { - var settings = new - { - id = id, - name = Id, - css = css, - placeholder = Placeholder, - hidedescription = HideDescription, - multiselect = MultiSelect - }; - - var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; - var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); - var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); - var builder = new StringBuilder(); - - builder.AppendLine($"let options = {optionsJson};"); - builder.AppendLine($"let settings = {settingsJson};"); - builder.AppendLine($"let container = $('#{id}');"); - builder.AppendLine($"let obj = new webexpress.webui.selectionCtrl(settings);"); - builder.AppendLine($"obj.options = options;"); - builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];"); - - if (OnChange != null) - { - builder.AppendLine($"obj.on('webexpress.webui.change.value', {OnChange});"); - } - - builder.AppendLine($"container.replaceWith(obj.getCtrl);"); - - return builder.ToString(); - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; +//using System.Text; +//using System.Text.Json; +//using WebExpress.WebCore.WebHtml; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputSelection : ControlFormItemInput +// { +// /// +// /// Returns the entries. +// /// +// public ICollection Options { get; } = []; + +// /// +// /// Returns or sets the label of the selected options. +// /// +// public string Placeholder { get; set; } + +// /// +// /// Returns or sets whether to display the description of the option or hide it. +// /// +// public bool HideDescription { get; set; } + +// /// +// /// Allows you to select multiple items. +// /// +// public bool MultiSelect { get; set; } + +// /// +// /// Returns or sets the OnChange attribute. +// /// +// public PropertyOnChange OnChange { get; set; } + +// /// +// /// Returns or sets the value. +// /// +// public virtual ICollection Values => base.Value != null ? base.Value.Split(';', System.StringSplitOptions.RemoveEmptyEntries) : []; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputSelection(string id = null) +// : base(id ?? Guid.NewGuid().ToString()) +// { +// Name = Id; +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The entries. +// public ControlFormItemInputSelection(string id, params ControlFormItemInputSelectionItem[] items) +// : this(id) +// { +// (Options as List).AddRange(items); +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// if (context.Request.HasParameter(Name)) +// { +// Value = context?.Request.GetParameter(Name)?.Value; +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var classes = Classes.ToList(); + +// if (Disabled) +// { +// classes.Add("disabled"); +// } + +// switch (ValidationResult) +// { +// case TypesInputValidity.Warning: +// classes.Add("input-warning"); +// break; +// case TypesInputValidity.Error: +// classes.Add("input-error"); +// break; +// } + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Style = GetStyles() +// }; + +// context.AddScript(Id, GetScript(context, Id, string.Join(" ", classes))); + +// return html; +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); +// } + +// /// +// /// Generates the javascript to control the control. +// /// +// /// The context in which the control is rendered. +// /// The ID of the control. +// /// The CSS classes that are assigned to the control. +// /// The javascript code. +// protected virtual string GetScript(RenderContextForm context, string id, string css) +// { +// var settings = new +// { +// id = id, +// name = Id, +// css = css, +// placeholder = Placeholder, +// hidedescription = HideDescription, +// multiselect = MultiSelect +// }; + +// var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; +// var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); +// var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); +// var builder = new StringBuilder(); + +// builder.AppendLine($"let options = {optionsJson};"); +// builder.AppendLine($"let settings = {settingsJson};"); +// builder.AppendLine($"let container = $('#{id}');"); +// builder.AppendLine($"let obj = new webexpress.webui.selectionCtrl(settings);"); +// builder.AppendLine($"obj.options = options;"); +// builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];"); + +// if (OnChange != null) +// { +// builder.AppendLine($"obj.on('webexpress.webui.change.value', {OnChange});"); +// } + +// builder.AppendLine($"container.replaceWith(obj.getCtrl);"); + +// return builder.ToString(); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs index 0dce5c70..3dd869eb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs @@ -1,49 +1,49 @@ -ο»Ώusing System.Text.Json.Serialization; +ο»Ώ//using System.Text.Json.Serialization; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputSelectionItem - { - /// - /// Returns or sets Returns or sets the id. - /// - [JsonPropertyName("id")] - public string Id { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputSelectionItem +// { +// /// +// /// Returns or sets Returns or sets the id. +// /// +// [JsonPropertyName("id")] +// public string Id { get; set; } - /// - /// Returns or sets the label. - /// - [JsonPropertyName("label")] - public string Label { get; set; } +// /// +// /// Returns or sets the label. +// /// +// [JsonPropertyName("label")] +// public string Label { get; set; } - /// - /// Returns or sets the css class of the icon. - /// - [JsonPropertyName("icon")] - public string Icon { get; set; } +// /// +// /// Returns or sets the css class of the icon. +// /// +// [JsonPropertyName("icon")] +// public string Icon { get; set; } - /// - /// Returns or sets the uri of the image. - /// - [JsonPropertyName("image")] - public string Image { get; set; } +// /// +// /// Returns or sets the uri of the image. +// /// +// [JsonPropertyName("image")] +// public string Image { get; set; } - /// - /// Returns or sets the description. - /// - [JsonPropertyName("description")] - public string Description { get; set; } +// /// +// /// Returns or sets the description. +// /// +// [JsonPropertyName("description")] +// public string Description { get; set; } - /// - /// Returns or sets the color. - /// - [JsonPropertyName("color")] - public string Color { get; set; } +// /// +// /// Returns or sets the color. +// /// +// [JsonPropertyName("color")] +// public string Color { get; set; } - /// - /// Returns or sets the command (e.g. Add). - /// - [JsonPropertyName("instruction")] - public string Instruction { get; set; } - } -} +// /// +// /// Returns or sets the command (e.g. Add). +// /// +// [JsonPropertyName("instruction")] +// public string Instruction { get; set; } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs index 830c0fcc..089f0351 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs @@ -1,212 +1,208 @@ -ο»Ώusing System; -using System.Linq; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebUri; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemInputTextBox : ControlFormItemInput - { - /// - /// Determines whether the control is automatically initialized. - /// - public bool AutoInitialize { get; set; } - - /// - /// Determines whether it is a multi-line text box. - /// - public TypesEditTextFormat Format { get; set; } - - /// - /// Returns or sets the description. - /// - public string Description { get; set; } - - /// - /// Returns or sets a placeholder text. - /// - public string Placeholder { get; set; } - - /// - /// Returns or sets the minimum length. - /// - public int? MinLength { get; set; } - - /// - /// Returns or sets the maximum length. - /// - public int? MaxLength { get; set; } - - /// - /// Returns or sets whether inputs are enforced. - /// - public bool Required { get; set; } - - /// - /// Returns or sets a search pattern that checks the content. - /// - public string Pattern { get; set; } - - /// - /// Returns or sets the height of the text fiel (for Multiline and WYSIWYG) - /// - public int Rows { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInputTextBox(string id = null) - : base(id) - { - Name = Id; - Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The name of the text box. - public ControlFormItemInputTextBox(string id, string name) - : base(id) - { - Name = name; - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - base.Initialize(context); - - Rows = 8; - AutoInitialize = true; - - Value = context?.Request.GetParameter(Name)?.Value; - - if (Format == TypesEditTextFormat.Wysiwyg) - { - var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module)); - if (module != null) - { - context.VisualTree.CssLinks.Add(UriResource.Combine(module.ContextPath, "/assets/css/summernote-bs5.min.css")); - context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(module.ContextPath, "/assets/js/summernote-bs5.min.js")); - } - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var id = Id ?? Guid.NewGuid().ToString(); - - Classes.Add("form-control"); - - if (Disabled) - { - Classes.Add("disabled"); - } - - switch (ValidationResult) - { - case TypesInputValidity.Warning: - Classes.Add("input-warning"); - break; - case TypesInputValidity.Error: - Classes.Add("input-error"); - break; - } - - if (AutoInitialize && Format == TypesEditTextFormat.Wysiwyg && !string.IsNullOrWhiteSpace(Id)) - { - var initializeCode = $"$(document).ready(function() {{ $('#{id}').summernote({{ tabsize: 2, height: '{Rows}rem', lang: 'de-DE' }}); }});"; - - context.AddScript(id, initializeCode); - - AutoInitialize = false; - } - - return Format switch - { - TypesEditTextFormat.Multiline => new HtmlElementFormTextarea() - { - Id = Id, - Value = Value, - Name = Name, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - Placeholder = I18N(context.Culture, Placeholder), - Rows = Rows.ToString() - }, - TypesEditTextFormat.Wysiwyg => new HtmlElementFormTextarea() - { - Id = id, - Value = Value, - Name = Name, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - Placeholder = I18N(context.Culture, Placeholder), - Rows = Rows.ToString() - }, - _ => new HtmlElementFieldInput() - { - Id = Id, - Value = Value, - Name = Name, - MinLength = MinLength?.ToString(), - MaxLength = MaxLength?.ToString(), - Required = Required, - Pattern = Pattern, - Type = "text", - Disabled = Disabled, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - Placeholder = I18N(context.Culture, Placeholder) - }, - }; - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public override void Validate(RenderContextForm context) - { - base.Validate(context); - - if (Disabled) - { - return; - } - - if (Required && string.IsNullOrWhiteSpace(base.Value)) - { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); - - return; - } - - if (!string.IsNullOrWhiteSpace(MinLength?.ToString()) && Convert.ToInt32(MinLength) > base.Value.Length) - { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N(context.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); - } - - if (!string.IsNullOrWhiteSpace(MaxLength?.ToString()) && Convert.ToInt32(MaxLength) < base.Value.Length) - { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N(context.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); - } - } - } -} +ο»Ώ//using System; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebUri; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemInputTextBox : ControlFormItemInput +// { +// /// +// /// Determines whether the control is automatically initialized. +// /// +// public bool AutoInitialize { get; set; } + +// /// +// /// Determines whether it is a multi-line text box. +// /// +// public TypesEditTextFormat Format { get; set; } + +// /// +// /// Returns or sets the description. +// /// +// public string Description { get; set; } + +// /// +// /// Returns or sets a placeholder text. +// /// +// public string Placeholder { get; set; } + +// /// +// /// Returns or sets the minimum length. +// /// +// public int? MinLength { get; set; } + +// /// +// /// Returns or sets the maximum length. +// /// +// public int? MaxLength { get; set; } + +// /// +// /// Returns or sets whether inputs are enforced. +// /// +// public bool Required { get; set; } + +// /// +// /// Returns or sets a search pattern that checks the content. +// /// +// public string Pattern { get; set; } + +// /// +// /// Returns or sets the height of the text fiel (for Multiline and WYSIWYG) +// /// +// public int Rows { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemInputTextBox(string id = null) +// : base(id) +// { +// Name = Id; +// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The name of the text box. +// public ControlFormItemInputTextBox(string id, string name) +// : base(id) +// { +// Name = name; +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// base.Initialize(context); + +// Rows = 8; +// AutoInitialize = true; + +// Value = context?.Request.GetParameter(Name)?.Value; + +// if (Format == TypesEditTextFormat.Wysiwyg) +// { +// var contextPath = context?.PageContext?.ApplicationContext?.ContextPath; +// context.VisualTree.CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); +// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var id = Id ?? Guid.NewGuid().ToString(); + +// Classes.Add("form-control"); + +// if (Disabled) +// { +// Classes.Add("disabled"); +// } + +// switch (ValidationResult) +// { +// case TypesInputValidity.Warning: +// Classes.Add("input-warning"); +// break; +// case TypesInputValidity.Error: +// Classes.Add("input-error"); +// break; +// } + +// if (AutoInitialize && Format == TypesEditTextFormat.Wysiwyg && !string.IsNullOrWhiteSpace(Id)) +// { +// var initializeCode = $"$(document).ready(function() {{ $('#{id}').summernote({{ tabsize: 2, height: '{Rows}rem', lang: 'de-DE' }}); }});"; + +// context.AddScript(id, initializeCode); + +// AutoInitialize = false; +// } + +// return Format switch +// { +// TypesEditTextFormat.Multiline => new HtmlElementFormTextarea() +// { +// Id = Id, +// Value = Value, +// Name = Name, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// Placeholder = I18N.Translate(context.Culture, Placeholder), +// Rows = Rows.ToString() +// }, +// TypesEditTextFormat.Wysiwyg => new HtmlElementFormTextarea() +// { +// Id = id, +// Value = Value, +// Name = Name, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// Placeholder = I18N.Translate(context.Culture, Placeholder), +// Rows = Rows.ToString() +// }, +// _ => new HtmlElementFieldInput() +// { +// Id = Id, +// Value = Value, +// Name = Name, +// MinLength = MinLength?.ToString(), +// MaxLength = MaxLength?.ToString(), +// Required = Required, +// Pattern = Pattern, +// Type = "text", +// Disabled = Disabled, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// Placeholder = I18N.Translate(context.Culture, Placeholder) +// }, +// }; +// } + +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// public override void Validate(RenderContextForm context) +// { +// base.Validate(context); + +// if (Disabled) +// { +// return; +// } + +// if (Required && string.IsNullOrWhiteSpace(base.Value)) +// { +// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); + +// return; +// } + +// if (!string.IsNullOrWhiteSpace(MinLength?.ToString()) && Convert.ToInt32(MinLength) > base.Value.Length) +// { +// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(context.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); +// } + +// if (!string.IsNullOrWhiteSpace(MaxLength?.ToString()) && Convert.ToInt32(MaxLength) < base.Value.Length) +// { +// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(context.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); +// } +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs index 97d0f287..a5215994 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs @@ -1,67 +1,67 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemLabel : ControlFormItem - { - /// - /// Returns or sets the text of the label. - /// - public string Text { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemLabel : ControlFormItem +// { +// /// +// /// Returns or sets the text of the label. +// /// +// public string Text { get; set; } - /// - /// Returns or sets the associated form field. - /// - public ControlFormItem FormItem { get; set; } +// /// +// /// Returns or sets the associated form field. +// /// +// public ControlFormItem FormItem { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemLabel(string id) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemLabel(string id) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlFormItemLabel(string id, string text) - : this(id) - { - Text = text; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlFormItemLabel(string id, string text) +// : this(id) +// { +// Text = text; +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - return new HtmlElementFieldLabel() - { - Text = I18N(context.Culture, Text), - Class = GetClasses(), - Style = GetStyles(), - Role = Role, - For = FormItem != null ? - string.IsNullOrWhiteSpace(FormItem.Id) ? - FormItem.Name : - FormItem.Id : - null - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// return new HtmlElementFieldLabel() +// { +// Text = I18N.Translate(context.Culture, Text), +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role, +// For = FormItem != null ? +// string.IsNullOrWhiteSpace(FormItem.Id) ? +// FormItem.Name : +// FormItem.Id : +// null +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs index bc8648bd..674d83d9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs @@ -1,75 +1,75 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemPanel : ControlFormItem - { - /// - /// Returns or sets the content. - /// - public IEnumerable Content { get; private set; } = new List(); +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemPanel : ControlFormItem +// { +// /// +// /// Returns or sets the content. +// /// +// public IEnumerable Content { get; private set; } = new List(); - /// - /// Returns or sets the arrangement of the content. - /// - public TypeDirection Direction - { - get => (TypeDirection)GetProperty(TypeDirection.Default); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the arrangement of the content. +// /// +// public TypeDirection Direction +// { +// get => (TypeDirection)GetProperty(TypeDirection.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Fixed or full-width adjustment. - /// - public TypePanelContainer Fluid - { - get => (TypePanelContainer)GetProperty(TypePanelContainer.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Fixed or full-width adjustment. +// /// +// public TypePanelContainer Fluid +// { +// get => (TypePanelContainer)GetProperty(TypePanelContainer.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemPanel(string id) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemPanel(string id) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlFormItemPanel(string id, IEnumerable content) - : base(id) - { - Content = content; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlFormItemPanel(string id, IEnumerable content) +// : base(id) +// { +// Content = content; +// } - /// - /// Initialization - /// - public override void Initialize(RenderContextForm context) - { - } +// /// +// /// Initialization +// /// +// public override void Initialize(RenderContextForm context) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = GetClasses(), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs index ca4c3370..a101066e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs @@ -1,71 +1,71 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemPrepend : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemPrepend(string id) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemPrepend : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemPrepend(string id) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlFormItemPrepend(string id, params Control[] content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlFormItemPrepend(string id, params Control[] content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlFormItemPrepend(string id, IEnumerable content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlFormItemPrepend(string id, IEnumerable content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlFormItemPrepend(string id, List content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlFormItemPrepend(string id, List content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Classes.Add("input-group-prepend"); - var html = base.Render(context); - return html; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Classes.Add("input-group-prepend"); +// var html = base.Render(context); +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs index 145cb57e..7b1c49f8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs @@ -1,59 +1,59 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; -namespace WebExpress.WebUI.WebControl -{ - public class ControlFormItemStaticText : ControlFormItem, IControlFormLabel - { - /// - /// Returns or sets the label. - /// - public string Label { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlFormItemStaticText : ControlFormItem, IControlFormLabel +// { +// /// +// /// Returns or sets the label. +// /// +// public string Label { get; set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemStaticText(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlFormItemStaticText(string id = null) +// : base(id) +// { +// } - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public override void Initialize(RenderContextForm context) - { - } +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public override void Initialize(RenderContextForm context) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContextForm context) - { - var c = new List - { - "form-control-static" - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(RenderContextForm context) +// { +// var c = new List +// { +// "form-control-static" +// }; - var html = new HtmlElementTextContentP() - { - Text = I18N(context.Culture, Text), - Class = Css.Concatenate(GetClasses()), - Style = Style.Concatenate(GetStyles()), - Role = Role - }; +// var html = new HtmlElementTextContentP() +// { +// Text = I18N.Translate(context.Culture, Text), +// Class = Css.Concatenate(GetClasses()), +// Style = Style.Concatenate(GetStyles()), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlHtml.cs b/src/WebExpress.WebUI/WebControl/ControlHtml.cs index 942b4b90..e6111c79 100644 --- a/src/WebExpress.WebUI/WebControl/ControlHtml.cs +++ b/src/WebExpress.WebUI/WebControl/ControlHtml.cs @@ -1,58 +1,58 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlHtml : Control - { - /// - /// Retruns or sets the html source code. - /// - public string Html { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlHtml : Control +// { +// /// +// /// Retruns or sets the html source code. +// /// +// public string Html { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlHtml(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlHtml(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlHtml(string id, int value) - : base(id) - { - Html = value.ToString(); +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlHtml(string id, int value) +// : base(id) +// { +// Html = value.ToString(); - Init(); - } +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlRaw - { - Html = Html - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlRaw +// { +// Html = Html +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlIcon.cs b/src/WebExpress.WebUI/WebControl/ControlIcon.cs index 48e987bb..a1381856 100644 --- a/src/WebExpress.WebUI/WebControl/ControlIcon.cs +++ b/src/WebExpress.WebUI/WebControl/ControlIcon.cs @@ -1,8 +1,11 @@ ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a control that displays an icon. + /// public class ControlIcon : Control { /// @@ -43,24 +46,16 @@ public PropertySizeText Size /// The id of the control. public ControlIcon(string id = null) : base(id) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() { Icon = new PropertyIcon(TypeIcon.None); } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) { if (Icon.IsUserIcon) { diff --git a/src/WebExpress.WebUI/WebControl/ControlImage.cs b/src/WebExpress.WebUI/WebControl/ControlImage.cs index 08ce6b3a..db50087a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlImage.cs +++ b/src/WebExpress.WebUI/WebControl/ControlImage.cs @@ -1,8 +1,11 @@ ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents an image control that can be rendered as HTML. + /// public class ControlImage : Control { /// @@ -29,28 +32,19 @@ public class ControlImage : Control /// Initializes a new instance of the class. /// /// The id of the control. - public ControlImage(string id = null) + /// The image source. + public ControlImage(string id = null, string uri = null) : base(id) { + Uri = uri; } /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The image source. - public ControlImage(string id, string source) - : base(id) - { - Uri = source; - } - - /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) { Classes.Add(HorizontalAlignment.ToClass()); diff --git a/src/WebExpress.WebUI/WebControl/ControlLine.cs b/src/WebExpress.WebUI/WebControl/ControlLine.cs index 179b9289..fbefac34 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLine.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLine.cs @@ -1,62 +1,62 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlLine : Control, IControlSplitButtonItem, IControlDropdownItem - { - /// - /// Returns or sets the text color. - /// - public new PropertyColorText TextColor { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlLine : Control, IControlSplitButtonItem, IControlDropdownItem +// { +// /// +// /// Returns or sets the text color. +// /// +// public new PropertyColorText TextColor { get; private set; } - /// - /// Returns or set the background color. - /// - public new PropertyColorBackground BackgroundColor { get; private set; } +// /// +// /// Returns or set the background color. +// /// +// public new PropertyColorBackground BackgroundColor { get; private set; } - /// - /// Returns or sets the color. - /// - public PropertyColorLine Color - { - get => (PropertyColorLine)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); - } +// /// +// /// Returns or sets the color. +// /// +// public PropertyColorLine Color +// { +// get => (PropertyColorLine)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlLine(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlLine(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentHr() - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentHr() +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index 46e21214..31d62d42 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -3,10 +3,13 @@ using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a hyperlink control. + /// public class ControlLink : Control, IControlLink { /// @@ -33,7 +36,7 @@ public TypeTextDecoration Decoration public string Text { get; set; } /// - /// Returns or sets the tooltip. + /// Returns or sets the title. /// public string Title { get; set; } @@ -53,24 +56,24 @@ public TypeTextDecoration Decoration public PropertyModal Modal { get; set; } = new PropertyModal(); /// - /// Returns or sets the content. + /// Returns or sets the icon. /// - public List Content { get; private set; } + public PropertyIcon Icon { get; set; } /// - /// Returns or sets the parameters that apply to the link. + /// Returns or sets a tooltip text. /// - public List Params { get; set; } + public string Tooltip { get; set; } /// - /// Returns or sets the icon. + /// Returns or sets the content. /// - public PropertyIcon Icon { get; set; } + public IEnumerable Content { get; private set; } = []; /// - /// Returns or sets a tooltip text. + /// Returns or sets the parameters that apply to the link. /// - public string Tooltip { get; set; } + public List Params { get; set; } = []; /// /// Return or specifies the vertical orientation.. @@ -90,79 +93,27 @@ public PropertySizeText Size set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlLink(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlLink(string id, string text) - : this(id) - { - Text = text; - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlLink(params Control[] content) - : this((string)null) - { - Content.AddRange(content); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlLink(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } - /// /// Initializes a new instance of the class. /// /// The id of the control. /// The content of the html element. - public ControlLink(string id, List content) + public ControlLink(string id = null, params Control[] content) : base(id) { Content = content; - Params = new List(); - } - - /// - /// Initialization - /// - private void Init() - { - Content = new List(); - Params = new List(); } /// /// Returns all local and temporary parameters. /// - /// The context in which the control is rendered. - /// The parameters. - public string GetParams(IPage page) + /// The context in which the control is rendered. + /// The parameters as a query string. + private string GetParams(Request request) { var dict = new Dictionary(); - // Übernahme der Parameter des Link + // transfer of the parameters from the request. if (Params != null) { foreach (var v in Params) @@ -189,9 +140,9 @@ public string GetParams(IPage page) /// /// The context in which the control is rendered. /// The control as html. - public override IHtmlNode Render(RenderContext context) + public override IHtmlNode Render(IRenderControlContext context) { - var param = GetParams(context?.Page); + var param = GetParams(context?.Request); var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) { @@ -201,7 +152,7 @@ public override IHtmlNode Render(RenderContext context) Role = Role, Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), Target = Target, - Title = InternationalizationManager.I18N(context.Culture, Title), + Title = string.IsNullOrEmpty(Title) ? I18N.Translate(context.Request.Culture, Tooltip) : I18N.Translate(context.Request.Culture, Title), OnClick = OnClick?.ToString() }; @@ -222,7 +173,7 @@ public override IHtmlNode Render(RenderContext context) if (!string.IsNullOrWhiteSpace(Text)) { - html.Elements.Add(new HtmlText(InternationalizationManager.I18N(context.Culture, Text))); + html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); } if (Modal == null || Modal.Type == TypeModal.None) @@ -231,12 +182,12 @@ public override IHtmlNode Render(RenderContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Modal) diff --git a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs index cc87f0a8..1b062b9b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs @@ -1,78 +1,78 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Display a list of links. - /// - public class ControlLinkList : Control - { - /// - /// Returns or sets the text.farbe des Namens - /// - public PropertyColorText NameColor { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Display a list of links. +// /// +// public class ControlLinkList : Control +// { +// /// +// /// Returns or sets the text.farbe des Namens +// /// +// public PropertyColorText NameColor { get; set; } - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } - /// - /// Returns or sets the name. - /// - public string Name { get; set; } +// /// +// /// Returns or sets the name. +// /// +// public string Name { get; set; } - /// - /// Returns or sets the links. - /// - public List Links { get; } = new List(); +// /// +// /// Returns or sets the links. +// /// +// public List Links { get; } = new List(); - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlLinkList(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlLinkList(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var icon = new HtmlElementTextSemanticsSpan() - { - Class = Icon?.ToClass() - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var icon = new HtmlElementTextSemanticsSpan() +// { +// Class = Icon?.ToClass() +// }; - var name = new HtmlElementTextSemanticsSpan(new HtmlText(context.I18N(Name))) - { - Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", - Class = NameColor?.ToClass() - }; +// var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Name))) +// { +// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", +// Class = NameColor?.ToClass() +// }; - var html = new HtmlElementTextContentDiv - ( - Icon != null && Icon.HasIcon ? icon : null, - Name != null ? name : null - ) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; +// var html = new HtmlElementTextContentDiv +// ( +// Icon != null && Icon.HasIcon ? icon : null, +// Name != null ? name : null +// ) +// { +// Id = Id, +// Class = GetClasses(), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; - html.Elements.AddRange(Links?.Select(x => x.Render(context))); +// html.Elements.AddRange(Links?.Select(x => x.Render(context))); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index 10de6f21..2a3d0cf3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -1,7 +1,7 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -22,74 +22,17 @@ public TypeLayoutList Layout /// /// Returns or sets the list entries. /// - public List Items { get; private set; } = new List(); - - /// - /// Returns or sets whether it's sorted or unsorted. - /// - public bool Sorted { get; set; } - - /// - /// Returns or sets whether to display a frame. - /// - public bool ShowBorder { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlList(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The list entries. - public ControlList(string id, params ControlListItem[] items) - : base(id) - { - Items.AddRange(items); - } - - /// - /// Initializes a new instance of the class. - /// - /// The list entries. - public ControlList(params ControlListItem[] items) - : this(null, items) - { - } + public IEnumerable Items { get; private set; } = []; /// /// Initializes a new instance of the class. /// /// The id of the control. /// The list entries. - public ControlList(string id, IEnumerable items) + public ControlList(string id = null, params ControlListItem[] items) : base(id) { - Items.AddRange(items); - } - - /// - /// Initializes a new instance of the class. - /// - /// The list entries. - public ControlList(IEnumerable items) - : this(null, items) - { - } - - /// - /// Initialization - /// - private void Init() - { - ShowBorder = true; + Items = items ?? []; } /// @@ -98,7 +41,7 @@ private void Init() /// The list entries. public void Add(IEnumerable items) { - Items.AddRange(items); + Items = Items.Concat(items); } /// @@ -107,28 +50,28 @@ public void Add(IEnumerable items) /// The list entry. public void Add(ControlListItem item) { - Items.Add(item); + Items = Items.Concat([item]); } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// + public override IHtmlNode Render(IRenderControlContext renderContext) { - return Render(context, Items); + return Render(renderContext, Items); } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. + /// The context in which the control is rendered. /// The list entries. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, IEnumerable items) + /// An HTML node representing the rendered control. + public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) { - var li = items.Where(x => x.Enable).Select(x => x.Render(context)).ToList(); + var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); switch (Layout) { case TypeLayoutList.Horizontal: diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index c141a7c6..acb78cc4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -1,16 +1,19 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a list item control that can contain other controls as its content. + /// public class ControlListItem : Control { /// /// Returns or sets the content. /// - public List Content { get; private set; } = new List(); + public IEnumerable Content { get; private set; } /// /// Returns or sets the ativity state of the list item. @@ -25,10 +28,10 @@ public TypeActive Active /// Initializes a new instance of the class. /// /// The id of the control. - public ControlListItem(string id = null) + public ControlListItem(string id = null, params Control[] content) : base(id) { - Init(); + Content = content ?? []; } /// @@ -36,57 +39,19 @@ public ControlListItem(string id = null) /// /// The id of the control. /// The content of the html element. - public ControlListItem(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItem(params Control[] content) - : this(null, content) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlListItem(string id, List content) + public ControlListItem(string id = null, IEnumerable content = null) : base(id) { - Content = content; - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItem(List content) - : this(null, content) - { - Content = content; - } - - /// - /// Initialization - /// - private void Init() - { + Content = content ?? []; } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// The list entries. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) { return new HtmlElementTextContentLi(Content.Where(x => x.Enable).Select(x => x.Render(context))) { diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs index c4774e5a..97c3da0c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs @@ -1,85 +1,85 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlListItemButton : ControlListItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlListItemButton(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlListItemButton : ControlListItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlListItemButton(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlListItemButton(string id, params Control[] content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlListItemButton(string id, params Control[] content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItemButton(params Control[] content) - : base(content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlListItemButton(params Control[] content) +// : base(content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlListItemButton(string id, List content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlListItemButton(string id, List content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItemButton(List content) - : base(content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlListItemButton(List content) +// : base(content) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementFieldButton(from x in Content select x.Render(context)) - { - Id = Id, - Class = Css.Concatenate("list-group-item-action", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementFieldButton(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = Css.Concatenate("list-group-item-action", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs index 2fa2e8dc..19d3b132 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs @@ -1,195 +1,195 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlListItemLink : ControlListItem - { - /// - /// Returns or sets the target uri. - /// - public Uri Uri { get; set; } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the target. - /// - public TypeTarget Target { get; set; } - - /// - /// Returns or sets the tooltip. - /// - public string Title { get; set; } - - /// - /// Returns or sets a tooltip text. - /// - public string Tooltip { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the parameters that apply to the link. - /// - public List Params { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlListItemLink(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlListItemLink(string id, params Control[] content) - : base(id, content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItemLink(params Control[] content) - : base(content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlListItemLink(string id, List content) - : base(id, content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlListItemLink(List content) - : base(content) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - } - - /// - /// Returns all local and temporary parameters. - /// - /// The context in which the control is rendered. - /// The parameters. - public string GetParams(IPage page) - { - var dict = new Dictionary(); - - // copying the parameters of the link - if (Params != null) - { - foreach (var v in Params) - { - if (v.Scope == ParameterScope.Parameter) - { - if (!dict.ContainsKey(v.Key.ToLower())) - { - dict.Add(v.Key.ToLower(), v); - } - else - { - dict[v.Key.ToLower()] = v; - } - } - } - } - - return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var param = GetParams(context?.Page); - - var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) - { - Id = Id, - Class = Css.Concatenate("list-group-item-action", GetClasses()), - Style = GetStyles(), - Role = Role, - Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), - Target = Target, - Title = Title, - OnClick = OnClick?.ToString() - }; - - if (Icon != null && Icon.HasIcon) - { - html.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - html.Elements.Add(new HtmlText(Text)); - } - - //if (Modal != null) - //{ - // html.AddUserAttribute("data-bs-toggle", "modal"); - // html.AddUserAttribute("data-bs-target", "#" + Modal.Id); - - // return new HtmlList(html, Modal.Render(context)); - //} - - if (!string.IsNullOrWhiteSpace(Tooltip)) - { - html.AddUserAttribute("data-bs-toggle", "tooltip"); - } - - return html; - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebMessage; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlListItemLink : ControlListItem +// { +// /// +// /// Returns or sets the target uri. +// /// +// public Uri Uri { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the target. +// /// +// public TypeTarget Target { get; set; } + +// /// +// /// Returns or sets the tooltip. +// /// +// public string Title { get; set; } + +// /// +// /// Returns or sets a tooltip text. +// /// +// public string Tooltip { get; set; } + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Returns or sets the parameters that apply to the link. +// /// +// public List Params { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlListItemLink(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlListItemLink(string id, params Control[] content) +// : base(id, content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlListItemLink(params Control[] content) +// : base(content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlListItemLink(string id, List content) +// : base(id, content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlListItemLink(List content) +// : base(content) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// } + +// /// +// /// Returns all local and temporary parameters. +// /// +// /// The context in which the control is rendered. +// /// The parameters. +// public string GetParams(IPage page) +// { +// var dict = new Dictionary(); + +// // copying the parameters of the link +// if (Params != null) +// { +// foreach (var v in Params) +// { +// if (v.Scope == ParameterScope.Parameter) +// { +// if (!dict.ContainsKey(v.Key.ToLower())) +// { +// dict.Add(v.Key.ToLower(), v); +// } +// else +// { +// dict[v.Key.ToLower()] = v; +// } +// } +// } +// } + +// return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var param = ""; // GetParams(context?.Page); + +// var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = Css.Concatenate("list-group-item-action", GetClasses()), +// Style = GetStyles(), +// Role = Role, +// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), +// Target = Target, +// Title = Title, +// OnClick = OnClick?.ToString() +// }; + +// if (Icon != null && Icon.HasIcon) +// { +// html.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// html.Elements.Add(new HtmlText(Text)); +// } + +// //if (Modal != null) +// //{ +// // html.AddUserAttribute("data-bs-toggle", "modal"); +// // html.AddUserAttribute("data-bs-target", "#" + Modal.Id); + +// // return new HtmlList(html, Modal.Render(context)); +// //} + +// if (!string.IsNullOrWhiteSpace(Tooltip)) +// { +// html.AddUserAttribute("data-bs-toggle", "tooltip"); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index 8d22de64..42d0334a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -1,22 +1,25 @@ ο»Ώusing System.Collections.Generic; using System.Linq; +using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a modal control that can display content in a modal dialog. + /// public class ControlModal : Control { /// /// Returns or sets the content. /// - public List Content { get; private set; } + public IEnumerable Content { get; private set; } = []; /// /// Returns or sets whether the fader effect should be used. /// - public bool Fade { get; set; } + public bool Fade { get; set; } = true; /// /// Returns or sets the header. @@ -42,10 +45,9 @@ public class ControlModal : Control /// Initializes a new instance of the class. /// /// The id of the control. - public ControlModal(string id) - : base(!string.IsNullOrWhiteSpace(id) ? id : "modal") + public ControlModal(string id = null) + : base(id) { - Init(); } /// @@ -68,22 +70,7 @@ public ControlModal(string id, string header) public ControlModal(string id, string header, params Control[] content) : this(id, header) { - if (content != null) - { - Content.AddRange(content); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - /// The content of the html element. - public ControlModal(string id, string text, IEnumerable content) - : this(id, text) - { - Content.AddRange(content); + Content = content ?? []; } /// @@ -95,25 +82,15 @@ public ControlModal(string id, string text, IEnumerable content) public ControlModal(string id = null, params Control[] content) : this(id, string.Empty) { - Content.AddRange(content); - } - - /// - /// Initialization - /// - private void Init() - { - //Id = !string.IsNullOrWhiteSpace(Id) ? Id : "modal"; - Content = new List(); - Fade = true; + Content = content ?? []; } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) { var classes = Classes.ToList(); classes.Add("modal"); @@ -123,7 +100,7 @@ public override IHtmlNode Render(RenderContext context) classes.Add("fade"); } - var headerText = new HtmlElementSectionH4(I18N(context.Culture, Header)) + var headerText = new HtmlElementSectionH4(I18N.Translate(renderContext.Request.Culture, Header)) { Class = "modal-title" }; @@ -140,14 +117,14 @@ public override IHtmlNode Render(RenderContext context) Class = "modal-header" }; - var body = new HtmlElementTextContentDiv(from x in Content select x.Render(context)) + var body = new HtmlElementTextContentDiv(from x in Content select x.Render(renderContext)) { Class = "modal-body" }; var footer = default(HtmlElementTextContentDiv); - var footerButton = new HtmlElementFieldButton(new HtmlText(I18N(context.Culture, "webexpress.webui:modal.close.label"))) + var footerButton = new HtmlElementFieldButton(new HtmlText(I18N.Translate(renderContext.Request.Culture, "webexpress.webui:modal.close.label"))) { Type = "button", Class = Css.Concatenate("btn", new PropertyColorButton(TypeColorButton.Primary).ToStyle()) @@ -181,19 +158,19 @@ public override IHtmlNode Render(RenderContext context) if (!string.IsNullOrWhiteSpace(OnShownCode)) { var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; - context.VisualTree.AddScript(Id + "_shown", shown); + renderContext.AddScript(Id + "_shown", shown); } if (!string.IsNullOrWhiteSpace(OnHiddenCode)) { var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; - context.VisualTree.AddScript(Id + "_hidden", hidden); + renderContext.AddScript(Id + "_hidden", hidden); } if (ShowIfCreated) { var show = "$('#" + Id + "').modal('show');"; - context.VisualTree.AddScript(Id + "_showifcreated", show); + renderContext.AddScript(Id + "_showifcreated", show); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs index c89cfccf..05efe6c4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs @@ -1,220 +1,220 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlModalForm : ControlModal - { - /// - /// Returns the form. - /// - public ControlForm Form { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlModalForm(string id = null) - : this(id, string.Empty, null) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The headline. - public ControlModalForm(string id, string header) - : this(id, header, null) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The form controls. - public ControlModalForm(string id, params ControlFormItem[] content) - : this(id, string.Empty, content) - { - - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The headline. - /// The form controls. - public ControlModalForm(string id, string header, params ControlFormItem[] content) - : base("modal_" + id, string.Empty, null) - { - Form = content != null ? new ControlForm(id, content) : new ControlForm(id); - Form.InitializeForm += OnInitializeForm; - Form.Validated += OnValidatedForm; - Header = header; - } - - /// - /// Adds a form control. - /// - /// The form item. - public void Add(params ControlFormItem[] item) - { - Form.Add(item); - } - - /// - /// Removes a form control. - /// - /// The form item. - public void Remove(ControlFormItem item) - { - Form.Remove(item); - } - - /// - /// Invoked when the form is initialized. - /// - /// The sender. - /// The event argument. - private void OnInitializeForm(object sender, FormEventArgs e) - { - ShowIfCreated = false; - } - - /// - /// Invoked when the form has been validated. - /// - /// The sender. - /// The event argument. - private void OnValidatedForm(object sender, ValidationResultEventArgs e) - { - if (!e.Valid) - { - ShowIfCreated = true; - Fade = false; - } - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return Render(context, Form.Items); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The form items. - /// The control as html. - public virtual IHtmlNode Render(RenderContext context, IEnumerable items) - { - var fade = Fade; - var classes = Classes.ToList(); - - var form = Form.Render(context, items) as HtmlElementFormForm; - - classes.Add("modal"); - - if (Fade) - { - classes.Add("fade"); - } - - var headerText = new HtmlElementSectionH4(I18N(context.Culture, Header)) - { - Class = "modal-title" - }; - - var headerButton = new HtmlElementFieldButton() - { - Class = "btn-close" - }; - headerButton.AddUserAttribute("aria-label", "close"); - headerButton.AddUserAttribute("data-bs-dismiss", "modal"); - - var header = new HtmlElementTextContentDiv(headerText, headerButton) - { - Class = "modal-header" - }; - - var formElements = form.Elements.Where(x => !(x is HtmlElementSectionFooter)); - - var body = new HtmlElementTextContentDiv(formElements) - { - Class = "modal-body" - }; - - var footer = default(HtmlElementTextContentDiv); - - var submitFooterButton = new ControlFormItemButton(); - - var cancelFooterButton = new ControlButtonLink() - { - Text = I18N(context.Culture, "webexpress.webui:modal.close.label") - }.Render(context) as HtmlElement; - - cancelFooterButton.AddUserAttribute("data-bs-dismiss", "modal"); - - footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderContextForm(context, Form)), cancelFooterButton) - { - Class = "modal-footer d-flex justify-content-between" - }; - - var content = new HtmlElementTextContentDiv(header, body, footer) - { - Class = "modal-content" - }; - - var dialog = new HtmlElementTextContentDiv(content) - { - Class = "modal-dialog", - Role = "document" - }; - - var html = new HtmlElementTextContentDiv(dialog) - { - Id = Id, - Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = "dialog" - }; - - if (!string.IsNullOrWhiteSpace(OnShownCode)) - { - var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; - context.VisualTree.AddScript(Id + "_shown", shown); - } - - if (!string.IsNullOrWhiteSpace(OnHiddenCode)) - { - var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; - context.VisualTree.AddScript(Id + "_hidden", hidden); - } - - if (ShowIfCreated) - { - var show = "$('#" + Id + "').modal('show');"; - context.VisualTree.AddScript(Id + "_showifcreated", show); - } - - form.Elements.Clear(); - form.Elements.Add(html); - - Fade = fade; - - return form; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlModalForm : ControlModal +// { +// /// +// /// Returns the form. +// /// +// public ControlForm Form { get; private set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlModalForm(string id = null) +// : this(id, string.Empty, null) +// { + +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The headline. +// public ControlModalForm(string id, string header) +// : this(id, header, null) +// { + +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The form controls. +// public ControlModalForm(string id, params ControlFormItem[] content) +// : this(id, string.Empty, content) +// { + +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The headline. +// /// The form controls. +// public ControlModalForm(string id, string header, params ControlFormItem[] content) +// : base("modal_" + id, string.Empty, null) +// { +// Form = content != null ? new ControlForm(id, content) : new ControlForm(id); +// Form.InitializeForm += OnInitializeForm; +// Form.Validated += OnValidatedForm; +// Header = header; +// } + +// /// +// /// Adds a form control. +// /// +// /// The form item. +// public void Add(params ControlFormItem[] item) +// { +// Form.Add(item); +// } + +// /// +// /// Removes a form control. +// /// +// /// The form item. +// public void Remove(ControlFormItem item) +// { +// Form.Remove(item); +// } + +// /// +// /// Invoked when the form is initialized. +// /// +// /// The sender. +// /// The event argument. +// private void OnInitializeForm(object sender, FormEventArgs e) +// { +// ShowIfCreated = false; +// } + +// /// +// /// Invoked when the form has been validated. +// /// +// /// The sender. +// /// The event argument. +// private void OnValidatedForm(object sender, ValidationResultEventArgs e) +// { +// if (!e.Valid) +// { +// ShowIfCreated = true; +// Fade = false; +// } +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return Render(context, Form.Items); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The form items. +// /// The control as html. +// public virtual IHtmlNode Render(IRenderContext context, IEnumerable items) +// { +// var fade = Fade; +// var classes = Classes.ToList(); + +// var form = Form.Render(context, items) as HtmlElementFormForm; + +// classes.Add("modal"); + +// if (Fade) +// { +// classes.Add("fade"); +// } + +// var headerText = new HtmlElementSectionH4(I18N.Translate(context.Culture, Header)) +// { +// Class = "modal-title" +// }; + +// var headerButton = new HtmlElementFieldButton() +// { +// Class = "btn-close" +// }; +// headerButton.AddUserAttribute("aria-label", "close"); +// headerButton.AddUserAttribute("data-bs-dismiss", "modal"); + +// var header = new HtmlElementTextContentDiv(headerText, headerButton) +// { +// Class = "modal-header" +// }; + +// var formElements = form.Elements.Where(x => !(x is HtmlElementSectionFooter)); + +// var body = new HtmlElementTextContentDiv(formElements) +// { +// Class = "modal-body" +// }; + +// var footer = default(HtmlElementTextContentDiv); + +// var submitFooterButton = new ControlFormItemButton(); + +// var cancelFooterButton = new ControlButtonLink() +// { +// Text = I18N.Translate(context.Culture, "webexpress.webui:modal.close.label") +// }.Render(context) as HtmlElement; + +// cancelFooterButton.AddUserAttribute("data-bs-dismiss", "modal"); + +// footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderContextForm(context, Form)), cancelFooterButton) +// { +// Class = "modal-footer d-flex justify-content-between" +// }; + +// var content = new HtmlElementTextContentDiv(header, body, footer) +// { +// Class = "modal-content" +// }; + +// var dialog = new HtmlElementTextContentDiv(content) +// { +// Class = "modal-dialog", +// Role = "document" +// }; + +// var html = new HtmlElementTextContentDiv(dialog) +// { +// Id = Id, +// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = "dialog" +// }; + +// if (!string.IsNullOrWhiteSpace(OnShownCode)) +// { +// var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; +// context.VisualTree.AddScript(Id + "_shown", shown); +// } + +// if (!string.IsNullOrWhiteSpace(OnHiddenCode)) +// { +// var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; +// context.VisualTree.AddScript(Id + "_hidden", hidden); +// } + +// if (ShowIfCreated) +// { +// var show = "$('#" + Id + "').modal('show');"; +// context.VisualTree.AddScript(Id + "_showifcreated", show); +// } + +// form.Elements.Clear(); +// form.Elements.Add(html); + +// Fade = fade; + +// return form; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs index 4d9bd8ba..b78e31e9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs @@ -1,126 +1,126 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlMultipleProgressBar : Control - { - /// - /// Returns or sets the format of the progress bar. - /// - public TypeFormatProgress Format { get; set; } - - /// - /// Returns or sets the value. - /// - public List Items { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlMultipleProgressBar(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The value. - public ControlMultipleProgressBar(string id, params ControlMultipleProgressBarItem[] items) - : this(id) - { - Items.AddRange(items); - } - - /// - /// Initialization - /// - private void Init() - { - Items = new List(); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var barClass = new List(); - - switch (Format) - { - case TypeFormatProgress.Colored: - barClass.Add("progress-bar"); - break; - - case TypeFormatProgress.Striped: - barClass.Add("progress-bar"); - barClass.Add("progress-bar-striped"); - break; - - case TypeFormatProgress.Animated: - barClass.Add("progress-bar"); - barClass.Add("progress-bar-striped"); - barClass.Add("progress-bar-animated"); - break; - - default: - return new HtmlElementFormProgress(Items.Select(x => x.Value).Sum() + "%") - { - Id = Id, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - Min = "0", - Max = "100", - Value = Items.Select(x => x.Value).Sum().ToString() - }; - } - - Classes.Add("progress"); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - - foreach (var v in Items) - { - var styles = new List - { - "width: " + v.Value + "%;" - }; - - var c = new List(barClass) - { - v.BackgroundColor.ToClass() - }; - - barClass.Add(v.Color.ToClass()); - - var bar = new HtmlElementTextContentDiv(new HtmlText(v.Text)) - { - Id = Id, - Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join(" ", styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - - html.Elements.Add(bar); - } - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlMultipleProgressBar : Control +// { +// /// +// /// Returns or sets the format of the progress bar. +// /// +// public TypeFormatProgress Format { get; set; } + +// /// +// /// Returns or sets the value. +// /// +// public List Items { get; private set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlMultipleProgressBar(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The value. +// public ControlMultipleProgressBar(string id, params ControlMultipleProgressBarItem[] items) +// : this(id) +// { +// Items.AddRange(items); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Items = new List(); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var barClass = new List(); + +// switch (Format) +// { +// case TypeFormatProgress.Colored: +// barClass.Add("progress-bar"); +// break; + +// case TypeFormatProgress.Striped: +// barClass.Add("progress-bar"); +// barClass.Add("progress-bar-striped"); +// break; + +// case TypeFormatProgress.Animated: +// barClass.Add("progress-bar"); +// barClass.Add("progress-bar-striped"); +// barClass.Add("progress-bar-animated"); +// break; + +// default: +// return new HtmlElementFormProgress(Items.Select(x => x.Value).Sum() + "%") +// { +// Id = Id, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// Min = "0", +// Max = "100", +// Value = Items.Select(x => x.Value).Sum().ToString() +// }; +// } + +// Classes.Add("progress"); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; + +// foreach (var v in Items) +// { +// var styles = new List +// { +// "width: " + v.Value + "%;" +// }; + +// var c = new List(barClass) +// { +// v.BackgroundColor.ToClass() +// }; + +// barClass.Add(v.Color.ToClass()); + +// var bar = new HtmlElementTextContentDiv(new HtmlText(v.Text)) +// { +// Id = Id, +// Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join(" ", styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; + +// html.Elements.Add(bar); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs index 33b1b5df..251516eb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs @@ -1,25 +1,25 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlMultipleProgressBarItem - { - /// - /// Returns or sets the text.farbe - /// - public PropertyColorText Color { get; set; } +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlMultipleProgressBarItem +// { +// /// +// /// Returns or sets the text.farbe +// /// +// public PropertyColorText Color { get; set; } - /// - /// Returns or set the background color. - /// - public PropertyColorBackground BackgroundColor { get; set; } +// /// +// /// Returns or set the background color. +// /// +// public PropertyColorBackground BackgroundColor { get; set; } - /// - /// Returns or sets the value. - /// - public int Value { get; set; } +// /// +// /// Returns or sets the value. +// /// +// public int Value { get; set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - } -} +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs index 726fca07..e6ee084d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs @@ -1,205 +1,205 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlNavigation : Control - { - /// - /// Returns or sets the layout. - /// - public TypeLayoutTab Layout - { - get => (TypeLayoutTab)GetProperty(TypeLayoutTab.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the horizontal arrangement. - /// - public new TypeHorizontalAlignmentTab HorizontalAlignment - { - get => (TypeHorizontalAlignmentTab)GetProperty(TypeHorizontalAlignmentTab.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets whether the tab tabs should be the same size. - /// - public TypeJustifiedTab Justified - { - get => (TypeJustifiedTab)GetProperty(TypeJustifiedTab.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the horizontal or vertical orientation. - /// - public TypeOrientationTab Orientation - { - get => (TypeOrientationTab)GetProperty(TypeOrientationTab.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the active color. - /// - public PropertyColorBackground ActiveColor { get; set; } = new PropertyColorBackground(); - - /// - /// Returns or sets the active text color. - /// - public PropertyColorText ActiveTextColor { get; set; } = new PropertyColorText(); - - /// - /// Returns or sets the link color. - /// - public PropertyColorText LinkColor { get; set; } = new PropertyColorText(); - - /// - /// Returns or sets the navigation items. - /// - public List Items { get; private set; } = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlNavigation(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The navigation items. - public ControlNavigation(params IControlNavigationItem[] items) - : base(null) - { - Items.AddRange(items); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlNavigation(string id, IEnumerable content) - : base(id) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlNavigation(IEnumerable content) - : base(null) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - //ActiveColor = LayoutSchema.NavigationActiveBackground; - //ActiveTextColor = LayoutSchema.NavigationActive; - //LinkColor = LayoutSchema.NavigationLink; - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var items = new List(); - foreach (var item in Items) - { - var i = item.Render(context) as HtmlElement; - - if (item is ControlNavigationItemLink link) - { - i.RemoveClass(link.TextColor?.ToClass()); - i.RemoveStyle(link.TextColor?.ToStyle()); - - i.AddClass - ( - Css.Concatenate - ( - "nav-link", - link.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", - link.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : LinkColor?.ToClass() - ) - ); - - i.AddStyle - ( - Style.Concatenate - ( - link.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", - link.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : LinkColor?.ToStyle() - ) - ); - - - } - else if (item is ControlNavigationItemDropdown dropdown) - { - i.RemoveClass(dropdown.TextColor?.ToClass()); - i.RemoveStyle(dropdown.TextColor?.ToStyle()); - - i.AddClass - ( - Css.Concatenate - ( - "nav-link", - dropdown.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", - dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : "" - ) - ); - i.AddStyle - ( - Style.Concatenate - ( - dropdown.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", - dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : "" - ) - ); - } - else - { - //i.AddClass(Css.Concatenate("nav-link")); - } - - items.Add(new HtmlElementTextContentLi(i) - { - Class = "nav-item" - }); - } - - var html = new HtmlElementTextContentUl(items) - { - Id = Id, - Class = Css.Concatenate("nav", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlNavigation : Control +// { +// /// +// /// Returns or sets the layout. +// /// +// public TypeLayoutTab Layout +// { +// get => (TypeLayoutTab)GetProperty(TypeLayoutTab.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the horizontal arrangement. +// /// +// public new TypeHorizontalAlignmentTab HorizontalAlignment +// { +// get => (TypeHorizontalAlignmentTab)GetProperty(TypeHorizontalAlignmentTab.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets whether the tab tabs should be the same size. +// /// +// public TypeJustifiedTab Justified +// { +// get => (TypeJustifiedTab)GetProperty(TypeJustifiedTab.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the horizontal or vertical orientation. +// /// +// public TypeOrientationTab Orientation +// { +// get => (TypeOrientationTab)GetProperty(TypeOrientationTab.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the active color. +// /// +// public PropertyColorBackground ActiveColor { get; set; } = new PropertyColorBackground(); + +// /// +// /// Returns or sets the active text color. +// /// +// public PropertyColorText ActiveTextColor { get; set; } = new PropertyColorText(); + +// /// +// /// Returns or sets the link color. +// /// +// public PropertyColorText LinkColor { get; set; } = new PropertyColorText(); + +// /// +// /// Returns or sets the navigation items. +// /// +// public List Items { get; private set; } = new List(); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlNavigation(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The navigation items. +// public ControlNavigation(params IControlNavigationItem[] items) +// : base(null) +// { +// Items.AddRange(items); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlNavigation(string id, IEnumerable content) +// : base(id) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlNavigation(IEnumerable content) +// : base(null) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// //ActiveColor = LayoutSchema.NavigationActiveBackground; +// //ActiveTextColor = LayoutSchema.NavigationActive; +// //LinkColor = LayoutSchema.NavigationLink; +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var items = new List(); +// foreach (var item in Items) +// { +// var i = item.Render(context) as HtmlElement; + +// if (item is ControlNavigationItemLink link) +// { +// i.RemoveClass(link.TextColor?.ToClass()); +// i.RemoveStyle(link.TextColor?.ToStyle()); + +// i.AddClass +// ( +// Css.Concatenate +// ( +// "nav-link", +// link.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", +// link.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : LinkColor?.ToClass() +// ) +// ); + +// i.AddStyle +// ( +// Style.Concatenate +// ( +// link.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", +// link.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : LinkColor?.ToStyle() +// ) +// ); + + +// } +// else if (item is ControlNavigationItemDropdown dropdown) +// { +// i.RemoveClass(dropdown.TextColor?.ToClass()); +// i.RemoveStyle(dropdown.TextColor?.ToStyle()); + +// i.AddClass +// ( +// Css.Concatenate +// ( +// "nav-link", +// dropdown.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", +// dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : "" +// ) +// ); +// i.AddStyle +// ( +// Style.Concatenate +// ( +// dropdown.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", +// dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : "" +// ) +// ); +// } +// else +// { +// //i.AddClass(Css.Concatenate("nav-link")); +// } + +// items.Add(new HtmlElementTextContentLi(i) +// { +// Class = "nav-item" +// }); +// } + +// var html = new HtmlElementTextContentUl(items) +// { +// Id = Id, +// Class = Css.Concatenate("nav", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs index da7bfadc..a6d69a17 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs @@ -1,27 +1,27 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlNavigationItemDropdown : ControlDropdown, IControlNavigationItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlNavigationItemDropdown(string id = null) - : base(id) - { - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlNavigationItemDropdown : ControlDropdown, IControlNavigationItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlNavigationItemDropdown(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return base.Render(context); - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return base.Render(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs index a9376e4c..b6007711 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs @@ -1,50 +1,50 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlNavigationItemHeader : Control, IControlNavigationItem - { - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlNavigationItemHeader : Control, IControlNavigationItem +// { +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlNavigationItemHeader(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlNavigationItemHeader(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlNavigationItemHeader(string id, string text) - : base(id) - { - Text = text; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlNavigationItemHeader(string id, string text) +// : base(id) +// { +// Text = text; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementTextContentLi(new HtmlText(I18N(context.Culture, Text))) - { - Id = Id, - Class = Css.Concatenate("dropdown-header", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(context.Culture, Text))) +// { +// Id = Id, +// Class = Css.Concatenate("dropdown-header", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs index 2b68561e..a3e76ff3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs @@ -1,39 +1,39 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlNavigationItemLink : ControlLink, IControlNavigationItem - { - /// - /// Verhindert den Zeilenumbruch - /// - public bool NoWrap { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlNavigationItemLink : ControlLink, IControlNavigationItem +// { +// /// +// /// Verhindert den Zeilenumbruch +// /// +// public bool NoWrap { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlNavigationItemLink(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlNavigationItemLink(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = base.Render(context); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = base.Render(context); - if (NoWrap) - { - html.AddClass("text-nowrap"); - } +// if (NoWrap) +// { +// html.AddClass("text-nowrap"); +// } - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPagination.cs b/src/WebExpress.WebUI/WebControl/ControlPagination.cs index d795f4d2..71b93a8f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPagination.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPagination.cs @@ -1,210 +1,210 @@ -ο»Ώusing System; -using System.Collections.Generic; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlPagination : Control - { - /// - /// Returns or sets the number of pages. - /// - public int PageCount { get; set; } - - /// - /// Returns or sets the page size. - /// - public int PageSize { get; set; } - - /// - /// Returns or sets the current page. - /// - public int PageOffset { get; set; } - - /// - /// Returns or sets the maximum number of side buttons. - /// - public int MaxDisplayCount { get; set; } - - /// - /// Returns or sets the size. - /// - public TypeSizePagination Size - { - get => (TypeSizePagination)GetProperty(TypeSizePagination.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPagination(string id = null) - : base(id) - { - MaxDisplayCount = 5; - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentUl() - { - Class = Css.Concatenate("pagination", Css.Remove(GetClasses(), BackgroundColor?.ToClass(), BorderColor?.ToClass())), - Style = Style.Remove(GetStyles(), BackgroundColor.ToStyle()), - Role = Role - }; - - if (PageOffset >= PageCount) - { - PageOffset = PageCount - 1; - } - - if (PageOffset < 0) - { - PageOffset = 0; - } - - if (PageOffset > 0 && PageCount > 1) - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink() - { - Params = Parameter.Create(new Parameter("offset", PageOffset - 1, ParameterScope.Parameter)), - Classes = new List(new[] { "page-link", "fas fa-angle-left", "border-0" }) - }.Render(context) - ) - { - Class = "page-item" - } - ); - } - else - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink() - { - Params = Parameter.Create(), - Classes = new List(new[] { "page-link", "fas fa-angle-left", "border-0" }) - }.Render(context) - ) - { - Class = "page-item disabled" - } - ); - } - - var buf = new List(MaxDisplayCount); - - var j = 0; - var k = 0; - - buf.Add(PageOffset); - while (buf.Count < Math.Min(PageCount, MaxDisplayCount)) - { - if (PageOffset + j + 1 < PageCount) - { - j += 1; - buf.Add(PageOffset + j); - } - - if (PageOffset - k - 1 >= 0) - { - k += 1; - buf.Add(PageOffset - k); - } - } - - buf.Sort(); - - foreach (var v in buf) - { - if (v == PageOffset) - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink(null, (v + 1).ToString()) - { - BackgroundColor = BackgroundColor, - Params = Parameter.Create(new Parameter("offset", v, ParameterScope.Parameter)), - Classes = new List() { Css.Concatenate("page-link border-0") }, - Styles = new List() { Style.Concatenate("", BackgroundColor.ToStyle()) } - }.Render(context) - ) - { - Class = "page-item active" - } - ); - } - else - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink(null, (v + 1).ToString()) - { - Params = Parameter.Create(new Parameter("offset", v, ParameterScope.Parameter)), - Classes = new List(new[] { "page-link border-0" }) - }.Render(context) - ) - { - Class = "page-item" - } - ); - } - } - - if (PageOffset < PageCount - 1) - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink() - { - Params = Parameter.Create(new Parameter("offset", PageOffset + 1, ParameterScope.Parameter)), - Classes = new List(new[] { "page-link", "fas fa-angle-right", "border-0" }) - }.Render(context) - ) - { - Class = "page-item" - } - ); - } - else - { - html.Elements.Add - ( - new HtmlElementTextContentLi - ( - new ControlLink() - { - Params = Parameter.Create(), - Classes = new List(new[] { "page-link", "fas fa-angle-right", "border-0" }) - }.Render(context) - ) - { - Class = "page-item disabled" - } - ); - } - - return html; - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebMessage; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPagination : Control +// { +// /// +// /// Returns or sets the number of pages. +// /// +// public int PageCount { get; set; } + +// /// +// /// Returns or sets the page size. +// /// +// public int PageSize { get; set; } + +// /// +// /// Returns or sets the current page. +// /// +// public int PageOffset { get; set; } + +// /// +// /// Returns or sets the maximum number of side buttons. +// /// +// public int MaxDisplayCount { get; set; } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizePagination Size +// { +// get => (TypeSizePagination)GetProperty(TypeSizePagination.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPagination(string id = null) +// : base(id) +// { +// MaxDisplayCount = 5; +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentUl() +// { +// Class = Css.Concatenate("pagination", Css.Remove(GetClasses(), BackgroundColor?.ToClass(), BorderColor?.ToClass())), +// Style = Style.Remove(GetStyles(), BackgroundColor.ToStyle()), +// Role = Role +// }; + +// if (PageOffset >= PageCount) +// { +// PageOffset = PageCount - 1; +// } + +// if (PageOffset < 0) +// { +// PageOffset = 0; +// } + +// if (PageOffset > 0 && PageCount > 1) +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink() +// { +// Params = Parameter.Create(new Parameter("offset", PageOffset - 1, ParameterScope.Parameter)), +// Classes = new List(new[] { "page-link", "fas fa-angle-left", "border-0" }) +// }.Render(context) +// ) +// { +// Class = "page-item" +// } +// ); +// } +// else +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink() +// { +// Params = Parameter.Create(), +// Classes = new List(new[] { "page-link", "fas fa-angle-left", "border-0" }) +// }.Render(context) +// ) +// { +// Class = "page-item disabled" +// } +// ); +// } + +// var buf = new List(MaxDisplayCount); + +// var j = 0; +// var k = 0; + +// buf.Add(PageOffset); +// while (buf.Count < Math.Min(PageCount, MaxDisplayCount)) +// { +// if (PageOffset + j + 1 < PageCount) +// { +// j += 1; +// buf.Add(PageOffset + j); +// } + +// if (PageOffset - k - 1 >= 0) +// { +// k += 1; +// buf.Add(PageOffset - k); +// } +// } + +// buf.Sort(); + +// foreach (var v in buf) +// { +// if (v == PageOffset) +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink(null, (v + 1).ToString()) +// { +// BackgroundColor = BackgroundColor, +// Params = Parameter.Create(new Parameter("offset", v, ParameterScope.Parameter)), +// Classes = new List() { Css.Concatenate("page-link border-0") }, +// Styles = new List() { Style.Concatenate("", BackgroundColor.ToStyle()) } +// }.Render(context) +// ) +// { +// Class = "page-item active" +// } +// ); +// } +// else +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink(null, (v + 1).ToString()) +// { +// Params = Parameter.Create(new Parameter("offset", v, ParameterScope.Parameter)), +// Classes = new List(new[] { "page-link border-0" }) +// }.Render(context) +// ) +// { +// Class = "page-item" +// } +// ); +// } +// } + +// if (PageOffset < PageCount - 1) +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink() +// { +// Params = Parameter.Create(new Parameter("offset", PageOffset + 1, ParameterScope.Parameter)), +// Classes = new List(new[] { "page-link", "fas fa-angle-right", "border-0" }) +// }.Render(context) +// ) +// { +// Class = "page-item" +// } +// ); +// } +// else +// { +// html.Elements.Add +// ( +// new HtmlElementTextContentLi +// ( +// new ControlLink() +// { +// Params = Parameter.Create(), +// Classes = new List(new[] { "page-link", "fas fa-angle-right", "border-0" }) +// }.Render(context) +// ) +// { +// Class = "page-item disabled" +// } +// ); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 084bb0a0..8d5fb7a5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -1,111 +1,111 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanel : Control - { - /// - /// Returns or sets the content. - /// - public List Content { get; private set; } = new List(); +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanel : Control +// { +// /// +// /// Returns or sets the content. +// /// +// public List Content { get; private set; } = new List(); - /// - /// Returns or sets the arrangement of the content. - /// - public TypeDirection Direction - { - get => (TypeDirection)GetProperty(TypeDirection.Default); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the arrangement of the content. +// /// +// public TypeDirection Direction +// { +// get => (TypeDirection)GetProperty(TypeDirection.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Fixed or full-width adjustment. - /// - public TypePanelContainer Fluid - { - get => (TypePanelContainer)GetProperty(TypePanelContainer.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Fixed or full-width adjustment. +// /// +// public TypePanelContainer Fluid +// { +// get => (TypePanelContainer)GetProperty(TypePanelContainer.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanel(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanel(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlPanel(params IControl[] content) - : this() - { - Content.AddRange(content.Where(x => x != null)); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlPanel(params IControl[] content) +// : this() +// { +// Content.AddRange(content.Where(x => x != null)); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlPanel(ICollection content) - : this() - { - Content.AddRange(content.Where(x => x != null)); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlPanel(ICollection content) +// : this() +// { +// Content.AddRange(content.Where(x => x != null)); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanel(string id, params IControl[] content) - : this(id) - { - Content.AddRange(content.Where(x => x != null)); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanel(string id, params IControl[] content) +// : this(id) +// { +// Content.AddRange(content.Where(x => x != null)); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanel(string id, IEnumerable content) - : this(id) - { - Content.AddRange(content.Where(x => x != null)); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanel(string id, IEnumerable content) +// : this(id) +// { +// Content.AddRange(content.Where(x => x != null)); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanel(string id, List content) - : base(id) - { - Content = content; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanel(string id, List content) +// : base(id) +// { +// Content = content; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = GetClasses(), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs index 8d92633c..5d48dfce 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs @@ -1,84 +1,84 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelCallout : ControlPanel - { - /// - /// Delivers or sets the title. - /// - public string Title { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelCallout : ControlPanel +// { +// /// +// /// Delivers or sets the title. +// /// +// public string Title { get; set; } - /// - /// Returns or sets the color. - /// - public PropertyColorCallout Color - { - get => (PropertyColorCallout)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); - } +// /// +// /// Returns or sets the color. +// /// +// public PropertyColorCallout Color +// { +// get => (PropertyColorCallout)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelCallout(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelCallout(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlPanelCallout(params Control[] content) - : this() - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlPanelCallout(params Control[] content) +// : this() +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanelCallout(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanelCallout(string id, params Control[] content) +// : this(id) +// { +// Content.AddRange(content); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("callout", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("callout", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - if (Title != null) - { - html.Elements.Add(new HtmlElementTextSemanticsSpan(new HtmlText(Title)) - { - Class = "callout-title" - }); - } +// if (Title != null) +// { +// html.Elements.Add(new HtmlElementTextSemanticsSpan(new HtmlText(Title)) +// { +// Class = "callout-title" +// }); +// } - html.Elements.Add(new HtmlElementTextContentDiv(from x in Content select x.Render(context)) - { - Class = "callout-body" - }); +// html.Elements.Add(new HtmlElementTextContentDiv(from x in Content select x.Render(context)) +// { +// Class = "callout-body" +// }); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs index a2e43f9c..11786942 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs @@ -1,144 +1,144 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Box with frame. - /// - public class ControlPanelCard : ControlPanel - { - /// - /// Returns or sets the header text. - /// - public string Header { get; set; } - - /// - /// Returns or sets the header image. - /// - public string HeaderImage { get; set; } - - /// - /// Returns or sets the headline. - /// - public string Headline { get; set; } - - /// - /// Returns or sets the footer. - /// - public string Footer { get; set; } - - /// - /// Returns or sets the footer image. - /// - public string FooterImage { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelCard(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelCard(string id, params Control[] items) - : base(id, items) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The controls to insert. - public ControlPanelCard(params Control[] items) - : base(items) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Border = new PropertyBorder(true); - } - - /// - /// Adds controls to the panel. - /// - /// The controls to insert. - public void Add(params Control[] items) - { - Content.AddRange(items); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("card", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - if (!string.IsNullOrWhiteSpace(Header)) - { - html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(context.I18N(Header))) { Class = "card-header" }); - } - - if (!string.IsNullOrWhiteSpace(HeaderImage)) - { - html.Elements.Add(new HtmlElementMultimediaImg() - { - Src = HeaderImage, - Class = "card-img-top" - }); - } - - if (!string.IsNullOrWhiteSpace(Headline)) - { - Content.Insert(0, new ControlText() - { - Text = context.I18N(Headline), - Classes = new List(["card-title"]), - Format = TypeFormatText.H4 - }); - } - - html.Elements.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "card-text" }) { Class = "card-body" }); - - if (!string.IsNullOrWhiteSpace(FooterImage)) - { - html.Elements.Add(new HtmlElementMultimediaImg() - { - Src = FooterImage, - Class = "card-img-top" - }); - } - - if (!string.IsNullOrWhiteSpace(Footer)) - { - html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(Footer)) { Class = "card-footer" }); - } - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Box with frame. +// /// +// public class ControlPanelCard : ControlPanel +// { +// /// +// /// Returns or sets the header text. +// /// +// public string Header { get; set; } + +// /// +// /// Returns or sets the header image. +// /// +// public string HeaderImage { get; set; } + +// /// +// /// Returns or sets the headline. +// /// +// public string Headline { get; set; } + +// /// +// /// Returns or sets the footer. +// /// +// public string Footer { get; set; } + +// /// +// /// Returns or sets the footer image. +// /// +// public string FooterImage { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelCard(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelCard(string id, params Control[] items) +// : base(id, items) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The controls to insert. +// public ControlPanelCard(params Control[] items) +// : base(items) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Border = new PropertyBorder(true); +// } + +// /// +// /// Adds controls to the panel. +// /// +// /// The controls to insert. +// public void Add(params Control[] items) +// { +// Content.AddRange(items); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("card", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// if (!string.IsNullOrWhiteSpace(Header)) +// { +// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(I18N.Translate(Header))) { Class = "card-header" }); +// } + +// if (!string.IsNullOrWhiteSpace(HeaderImage)) +// { +// html.Elements.Add(new HtmlElementMultimediaImg() +// { +// Src = HeaderImage, +// Class = "card-img-top" +// }); +// } + +// if (!string.IsNullOrWhiteSpace(Headline)) +// { +// Content.Insert(0, new ControlText() +// { +// Text = I18N.Translate(Headline), +// Classes = new List(["card-title"]), +// Format = TypeFormatText.H4 +// }); +// } + +// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "card-text" }) { Class = "card-body" }); + +// if (!string.IsNullOrWhiteSpace(FooterImage)) +// { +// html.Elements.Add(new HtmlElementMultimediaImg() +// { +// Src = FooterImage, +// Class = "card-img-top" +// }); +// } + +// if (!string.IsNullOrWhiteSpace(Footer)) +// { +// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(Footer)) { Class = "card-footer" }); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs index 2ee5f844..0eb870d2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs @@ -1,65 +1,65 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelCenter : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelCenter(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelCenter : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelCenter(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlPanelCenter(params Control[] content) - : this() - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlPanelCenter(params Control[] content) +// : this() +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanelCenter(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanelCenter(string id, params Control[] content) +// : this(id) +// { +// Content.AddRange(content); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv(from x in Content select x.Render(context)) - { - Id = Id, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs b/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs index 86364ca9..203a62f5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelDialog.cs @@ -1,23 +1,23 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlPanelDialog : ControlForm - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelDialog(string id = null) - : base(id) - { - Init(); - } +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelDialog : ControlForm +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelDialog(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { +// /// +// /// Initialization +// /// +// private void Init() +// { - } - } -} +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs index 51fe0352..95b0dbb5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFilter.cs @@ -1,22 +1,22 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlPanelFilter : ControlForm - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelFilter(string id = null) - : base(id) - { - Init(); - } +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelFilter : ControlForm +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelFilter(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } - } -} +// /// +// /// Initialization +// /// +// private void Init() +// { +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs index cf4280fa..28032fc0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs @@ -1,113 +1,113 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelFlexbox : ControlPanel - { - /// - /// Returns or sets whether the items should be displayed inline. - /// - public virtual TypeLayoutFlexbox Layout - { - get => (TypeLayoutFlexbox)GetProperty(TypeLayoutFlexbox.Default); - set => SetProperty(value, () => value.ToClass()); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelFlexbox : ControlPanel +// { +// /// +// /// Returns or sets whether the items should be displayed inline. +// /// +// public virtual TypeLayoutFlexbox Layout +// { +// get => (TypeLayoutFlexbox)GetProperty(TypeLayoutFlexbox.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the horizontal alignment of the items. - /// - public virtual TypeJustifiedFlexbox Justify - { - get => (TypeJustifiedFlexbox)GetProperty(TypeJustifiedFlexbox.Start); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the horizontal alignment of the items. +// /// +// public virtual TypeJustifiedFlexbox Justify +// { +// get => (TypeJustifiedFlexbox)GetProperty(TypeJustifiedFlexbox.Start); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Bestimmt, ob Specifies or sets the vertical orientation of the items. - /// - public virtual TypeAlignFlexbox Align - { - get => (TypeAlignFlexbox)GetProperty(TypeAlignFlexbox.Start); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Bestimmt, ob Specifies or sets the vertical orientation of the items. +// /// +// public virtual TypeAlignFlexbox Align +// { +// get => (TypeAlignFlexbox)GetProperty(TypeAlignFlexbox.Start); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the overflow behavior of the items. - /// - public virtual TypeWrap Wrap - { - get => (TypeWrap)GetProperty(TypeWrap.Nowrap); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the overflow behavior of the items. +// /// +// public virtual TypeWrap Wrap +// { +// get => (TypeWrap)GetProperty(TypeWrap.Nowrap); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelFlexbox(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelFlexbox(string id = null) +// : base(id) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The flexbox items. - public ControlPanelFlexbox(string id, params IControl[] content) - : base(id, content) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The flexbox items. +// public ControlPanelFlexbox(string id, params IControl[] content) +// : base(id, content) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The flexbox items. - public ControlPanelFlexbox(params IControl[] content) - : base(null, content) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The flexbox items. +// public ControlPanelFlexbox(params IControl[] content) +// : base(null, content) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The flexbox items. - public ControlPanelFlexbox(string id, IEnumerable content) - : base(id, content) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The flexbox items. +// public ControlPanelFlexbox(string id, IEnumerable content) +// : base(id, content) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The flexbox items. - public ControlPanelFlexbox(IEnumerable content) - : base(null, content) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The flexbox items. +// public ControlPanelFlexbox(IEnumerable content) +// : base(null, content) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - html.Elements.AddRange(Content.Select(x => x.Render(context))); +// html.Elements.AddRange(Content.Select(x => x.Render(context))); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs index cd9ee807..30d42a5d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs @@ -1,66 +1,66 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelFooter : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelFooter(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelFooter : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelFooter(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanelFooter(string id, params Control[] content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanelFooter(string id, params Control[] content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanelFooter(string id, List content) - : base(id, content) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanelFooter(string id, List content) +// : base(id, content) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - Content.Add(new ControlPanel(new ControlLine())); - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// Content.Add(new ControlPanel(new ControlLine())); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementSectionFooter(from x in Content select x.Render(context)) - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementSectionFooter(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs index 6826970a..4ba51fc3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs @@ -1,50 +1,50 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Grid of 12 cells per row. - /// - public class ControlPanelGrid : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelGrid(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Grid of 12 cells per row. +// /// +// public class ControlPanelGrid : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelGrid(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { +// /// +// /// Initialization +// /// +// private void Init() +// { - } +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; - html.Elements.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "row" }); +// html.Elements.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "row" }); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs index 45f8da2c..e50df866 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs @@ -1,81 +1,81 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelHeader : ControlPanel - { - /// - /// Returns or sets the fixed arrangement. - /// - public virtual TypeFixed Fixed - { - get => (TypeFixed)GetProperty(TypeFixed.None); - set => SetProperty(value, () => value.ToClass()); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelHeader : ControlPanel +// { +// /// +// /// Returns or sets the fixed arrangement. +// /// +// public virtual TypeFixed Fixed +// { +// get => (TypeFixed)GetProperty(TypeFixed.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the pinned arrangement when the toolbar is at the top. - /// - public virtual TypeSticky Sticky - { - get => (TypeSticky)GetProperty(TypeSticky.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Returns or sets the pinned arrangement when the toolbar is at the top. +// /// +// public virtual TypeSticky Sticky +// { +// get => (TypeSticky)GetProperty(TypeSticky.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelHeader(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelHeader(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlPanelHeader(params Control[] content) - : this() - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlPanelHeader(params Control[] content) +// : this() +// { +// Content.AddRange(content); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlPanelHeader(string id, params Control[] content) - : this(id) - { - Content.AddRange(content); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlPanelHeader(string id, params Control[] content) +// : this(id) +// { +// Content.AddRange(content); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementSectionHeader(from x in Content select x.Render(context)) - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementSectionHeader(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs index 10ec29cb..96d4d687 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs @@ -1,38 +1,38 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelMain : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelMain(string id = null) - : base(id) - { - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelMain : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelMain(string id = null) +// : base(id) +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementSectionMain() - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementSectionMain() +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; - html.Elements.AddRange(from x in Content select x?.Render(context)); +// html.Elements.AddRange(from x in Content select x?.Render(context)); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs index 17f5ebdb..f43356e3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs @@ -1,98 +1,98 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelMedia : ControlPanel - { - /// - /// Returns or sets the title. - /// - public Control Title { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelMedia : ControlPanel +// { +// /// +// /// Returns or sets the title. +// /// +// public Control Title { get; set; } - /// - /// Returns or sets the uri to the image. - /// - public string Image { get; set; } +// /// +// /// Returns or sets the uri to the image. +// /// +// public string Image { get; set; } - /// - /// Returns or sets the width of the image in pixel. - /// - public int ImageWidth { get; set; } = -1; +// /// +// /// Returns or sets the width of the image in pixel. +// /// +// public int ImageWidth { get; set; } = -1; - /// - /// Returns or sets the height of the image in pixel. - /// - public int ImageHeight { get; set; } = -1; +// /// +// /// Returns or sets the height of the image in pixel. +// /// +// public int ImageHeight { get; set; } = -1; - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelMedia(string id = null) - : base(id) - { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelMedia(string id = null) +// : base(id) +// { - } +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The headline. - public ControlPanelMedia(string id, string title) - : this(id) - { - Title = new ControlText(string.IsNullOrWhiteSpace(id) ? null : id + "_header") - { - Text = title - }; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The headline. +// public ControlPanelMedia(string id, string title) +// : this(id) +// { +// Title = new ControlText(string.IsNullOrWhiteSpace(id) ? null : id + "_header") +// { +// Text = title +// }; +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var img = new HtmlElementMultimediaImg() - { - Src = Image?.ToString(), - Class = "me-3 mt-3 " // rounded-circle - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var img = new HtmlElementMultimediaImg() +// { +// Src = Image?.ToString(), +// Class = "me-3 mt-3 " // rounded-circle +// }; - if (ImageWidth > -1) - { - img.Width = ImageWidth; - } +// if (ImageWidth > -1) +// { +// img.Width = ImageWidth; +// } - if (ImageHeight > -1) - { - img.Height = ImageHeight; - } +// if (ImageHeight > -1) +// { +// img.Height = ImageHeight; +// } - var heading = new HtmlElementSectionH4(Title?.Render(context)) - { - }; +// var heading = new HtmlElementSectionH4(Title?.Render(context)) +// { +// }; - var body = new HtmlElementTextContentDiv(Title != null ? heading : null) - { - Class = "media-body" - }; +// var body = new HtmlElementTextContentDiv(Title != null ? heading : null) +// { +// Class = "media-body" +// }; - body.Elements.AddRange(from x in Content select x.Render(context)); +// body.Elements.AddRange(from x in Content select x.Render(context)); - var html = new HtmlElementTextContentDiv(img, body) - { - Id = Id, - Class = Css.Concatenate("media", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// var html = new HtmlElementTextContentDiv(img, body) +// { +// Id = Id, +// Class = Css.Concatenate("media", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs index 356df643..f11dbc5a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs @@ -1,67 +1,67 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlPanelNavbar : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelNavbar(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelNavbar : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelNavbar(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The navbar items. - public ControlPanelNavbar(string id, params Control[] items) - : base(id, items) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The navbar items. +// public ControlPanelNavbar(string id, params Control[] items) +// : base(id, items) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The navbar items. - public ControlPanelNavbar(params Control[] items) - : base(items) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The navbar items. +// public ControlPanelNavbar(params Control[] items) +// : base(items) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementSectionNav() - { - Id = Id, - Class = Css.Concatenate("navbar", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementSectionNav() +// { +// Id = Id, +// Class = Css.Concatenate("navbar", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - html.Elements.AddRange(from x in Content select x?.Render(context)); +// html.Elements.AddRange(from x in Content select x?.Render(context)); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs index f1b2406d..f5f78004 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs @@ -1,165 +1,161 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebUri; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Two panels that can be resized by a variable splitter. - /// - public class ControlPanelSplit : Control - { - /// - /// Returns or sets whether the splitter is horziontal or vertically oriented. - /// - public TypeOrientationSplit Orientation { get; set; } - - /// - /// Returns or sets the color of the splitter. - /// - public PropertyColorBackground SplitterColor { get; set; } = new PropertyColorBackground(TypeColorBackground.Light); - - /// - /// Returns or sets the width of the splitter. - /// - public int SplitterSize { get; set; } = 6; - - /// - /// Returns the left or top panel in the ControlPanelSplit. - /// - public List Panel1 { get; } = new List(); - - /// - /// Returns or sets the minimum size of the left or top area in the ControlPanelSplit. - /// - public int Panel1MinSize { get; set; } - - /// - /// Returns or sets the initial size of the left or top area in the ControlPanelSplit in %. - /// - public int Panel1InitialSize { get; set; } = -1; - - /// - /// Returns the right or bottom pane in the ControlPanelSplit. - /// - public List Panel2 { get; } = new List(); - - /// - /// Returns or sets the minimum size of the right or bottom area in the ControlPanelSplit. - /// - public int Panel2MinSize { get; set; } - - /// - /// Returns or sets the initial size of the right or bottom area in the ControlPanelSplit in %. - /// - public int Panel2InitialSize { get; set; } = -1; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelSplit(string id = null) - : base(id) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// Left or top panel controls. - /// Right or bottom panel controls. - public ControlPanelSplit(string id, Control[] panel1, Control[] panel2) - : base(id) - { - Panel1.AddRange(panel1); - Panel2.AddRange(panel2); - } - - /// - /// Initializes a new instance of the class. - /// - /// Left or top panel controls. - /// Right or bottom panel controls. - public ControlPanelSplit(Control[] panel1, Control[] panel2) - : this(null, panel1, panel2) - { - } - - /// - /// Initializes the form element. - /// - /// The context in which the control is rendered. - public void Initialize(RenderContext context) - { - var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module)); - if (module != null) - { - context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(module.ContextPath, "/assets/js/split.min.js")); - } - - Border = new PropertyBorder(true); - - var init1 = 0; - var init2 = 0; - - if (Panel1InitialSize < 0 && Panel2InitialSize < 0) - { - init1 = init2 = 50; - } - else if (Panel1InitialSize < 0) - { - init1 = 100 - Panel2InitialSize; - init2 = Panel2InitialSize; - } - else if (Panel2InitialSize < 0) - { - init1 = Panel1InitialSize; - init2 = 100 - Panel1InitialSize; - } - - context.VisualTree.AddScript - ( - Id, @"Split(['#" + Id + "-p1', '#" + Id + @"-p2'], { - sizes: [" + init1 + "," + init2 + @"], - minSize: [" + Panel1MinSize + "," + Panel2MinSize + @"], - direction: '" + Orientation.ToString().ToLower() + @"', - gutter: function (index, direction) - { - var gutter = document.createElement('div'); - gutter.className = 'splitter splitter-' + direction + ' " + SplitterColor.ToClass() + @"'; - gutter.style = '" + SplitterColor.ToStyle() + @"'; - return gutter; - }, - gutterSize: " + SplitterSize + @", - });" - ); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Initialize(context); - - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate(Orientation == TypeOrientationSplit.Horizontal ? "d-flex split" : "split", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - html.Elements.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(context))) { Id = $"{Id}-p1" }); - html.Elements.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(context))) { Id = $"{Id}-p2" }); - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; +//using WebExpress.WebCore.WebUri; + +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Two panels that can be resized by a variable splitter. +// /// +// public class ControlPanelSplit : Control +// { +// /// +// /// Returns or sets whether the splitter is horziontal or vertically oriented. +// /// +// public TypeOrientationSplit Orientation { get; set; } + +// /// +// /// Returns or sets the color of the splitter. +// /// +// public PropertyColorBackground SplitterColor { get; set; } = new PropertyColorBackground(TypeColorBackground.Light); + +// /// +// /// Returns or sets the width of the splitter. +// /// +// public int SplitterSize { get; set; } = 6; + +// /// +// /// Returns the left or top panel in the ControlPanelSplit. +// /// +// public List Panel1 { get; } = new List(); + +// /// +// /// Returns or sets the minimum size of the left or top area in the ControlPanelSplit. +// /// +// public int Panel1MinSize { get; set; } + +// /// +// /// Returns or sets the initial size of the left or top area in the ControlPanelSplit in %. +// /// +// public int Panel1InitialSize { get; set; } = -1; + +// /// +// /// Returns the right or bottom pane in the ControlPanelSplit. +// /// +// public List Panel2 { get; } = new List(); + +// /// +// /// Returns or sets the minimum size of the right or bottom area in the ControlPanelSplit. +// /// +// public int Panel2MinSize { get; set; } + +// /// +// /// Returns or sets the initial size of the right or bottom area in the ControlPanelSplit in %. +// /// +// public int Panel2InitialSize { get; set; } = -1; + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelSplit(string id = null) +// : base(id) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// Left or top panel controls. +// /// Right or bottom panel controls. +// public ControlPanelSplit(string id, Control[] panel1, Control[] panel2) +// : base(id) +// { +// Panel1.AddRange(panel1); +// Panel2.AddRange(panel2); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// Left or top panel controls. +// /// Right or bottom panel controls. +// public ControlPanelSplit(Control[] panel1, Control[] panel2) +// : this(null, panel1, panel2) +// { +// } + +// /// +// /// Initializes the form element. +// /// +// /// The context in which the control is rendered. +// public void Initialize(RenderContext context) +// { +// var contextPath = context?.PageContext?.ApplicationContext?.ContextPath; +// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/split.min.js")); + +// Border = new PropertyBorder(true); + +// var init1 = 0; +// var init2 = 0; + +// if (Panel1InitialSize < 0 && Panel2InitialSize < 0) +// { +// init1 = init2 = 50; +// } +// else if (Panel1InitialSize < 0) +// { +// init1 = 100 - Panel2InitialSize; +// init2 = Panel2InitialSize; +// } +// else if (Panel2InitialSize < 0) +// { +// init1 = Panel1InitialSize; +// init2 = 100 - Panel1InitialSize; +// } + +// context.VisualTree.AddScript +// ( +// Id, @"Split(['#" + Id + "-p1', '#" + Id + @"-p2'], { +// sizes: [" + init1 + "," + init2 + @"], +// minSize: [" + Panel1MinSize + "," + Panel2MinSize + @"], +// direction: '" + Orientation.ToString().ToLower() + @"', +// gutter: function (index, direction) +// { +// var gutter = document.createElement('div'); +// gutter.className = 'splitter splitter-' + direction + ' " + SplitterColor.ToClass() + @"'; +// gutter.style = '" + SplitterColor.ToStyle() + @"'; +// return gutter; +// }, +// gutterSize: " + SplitterSize + @", +// });" +// ); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Initialize(context); + +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate(Orientation == TypeOrientationSplit.Horizontal ? "d-flex split" : "split", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// html.Elements.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(context))) { Id = $"{Id}-p1" }); +// html.Elements.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(context))) { Id = $"{Id}-p2" }); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs index 3d8af878..f3461a36 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs @@ -1,14 +1,14 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlPanelToast : ControlPanel - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelToast(string id) - : base(id) - { - } - } -} +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlPanelToast : ControlPanel +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelToast(string id) +// : base(id) +// { +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs index 84d4599d..48d5858f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs @@ -1,85 +1,85 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Box with superimposed tools. - /// - public class ControlPanelTool : ControlPanel - { - /// - /// Returns or sets the tools - /// - public ControlDropdown Tools { get; } = new ControlDropdown(); +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Box with superimposed tools. +// /// +// public class ControlPanelTool : ControlPanel +// { +// /// +// /// Returns or sets the tools +// /// +// public ControlDropdown Tools { get; } = new ControlDropdown(); - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelTool(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelTool(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelTool(string id, params Control[] items) - : base(id, items) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelTool(string id, params Control[] items) +// : base(id, items) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlPanelTool(params Control[] items) - : base(items) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlPanelTool(params Control[] items) +// : base(items) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - Border = new PropertyBorder(true); - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// Border = new PropertyBorder(true); +// } - /// - /// Adds controls to the panel. - /// - /// The controls to insert. - public void Add(params Control[] items) - { - Content.AddRange(items); - } +// /// +// /// Adds controls to the panel. +// /// +// /// The controls to insert. +// public void Add(params Control[] items) +// { +// Content.AddRange(items); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var dropDown = Tools.Render(context); - var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var dropDown = Tools.Render(context); +// var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))); - var html = new HtmlElementTextContentDiv(dropDown, content) - { - Id = Id, - Class = Css.Concatenate("toolpanel", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// var html = new HtmlElementTextContentDiv(dropDown, content) +// { +// Id = Id, +// Class = Css.Concatenate("toolpanel", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs index ce0d98a6..f87ae725 100644 --- a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs @@ -1,154 +1,154 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlProgressBar : Control - { - /// - /// Returns or sets the format of the progress bar. - /// - public TypeFormatProgress Format { get; set; } - - /// - /// Returns or sets the size. - /// - public TypeSizeProgress Size - { - get => (TypeSizeProgress)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass(), () => value.ToStyle()); - } - - /// - /// Returns or sets the progress bar color. - /// - public PropertyColorProgress Color { get; set; } - - /// - /// Returns or sets the text color. - /// - public new PropertyColorText TextColor { get; set; } - - /// - /// Returns or sets the value. - /// - public int Value { get; set; } - - /// - /// Returns or sets the minimum value. - /// - public int Min { get; set; } - - /// - /// Returns or sets the maximum value. - /// - public int Max { get; set; } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlProgressBar(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The value. - public ControlProgressBar(string id, int value) - : this(id) - { - Value = value; - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The value. - public ControlProgressBar(string id, int value, int min = 0, int max = 100) - : this(id) - { - Value = value; - Min = min; - Max = max; - } - - /// - /// Initialization - /// - private void Init() - { - Min = 0; - Max = 100; - BackgroundColor = new PropertyColorBackground(TypeColorBackground.Default); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - if (Format == TypeFormatProgress.Default) - { - return new HtmlElementFormProgress(Value + "%") - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role, - Min = Min.ToString(), - Max = Max.ToString(), - Value = Value.ToString() - }; - } - - var bar = new HtmlElementTextContentDiv(new HtmlText(Text)) - { - Role = "progressbar", - Class = Css.Concatenate - ( - "progress-bar", - Color?.ToClass(), - TextColor?.ToClass(), - Format.ToClass() - ), - Style = Css.Concatenate - ( - "width: " + Value + "%;", - Color?.ToStyle(), - TextColor?.ToStyle() - ) - }; - bar.AddUserAttribute("aria-valuenow", Value.ToString()); - bar.AddUserAttribute("aria-valuemin", Min.ToString()); - bar.AddUserAttribute("aria-valuemax", Max.ToString()); - - var html = new HtmlElementTextContentDiv(bar) - { - Id = Id, - Role = Role, - Class = Css.Concatenate - ( - "progress", - GetClasses() - ), - Style = GetStyles() - }; - - return html; - - } - } -} +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlProgressBar : Control +// { +// /// +// /// Returns or sets the format of the progress bar. +// /// +// public TypeFormatProgress Format { get; set; } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeProgress Size +// { +// get => (TypeSizeProgress)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass(), () => value.ToStyle()); +// } + +// /// +// /// Returns or sets the progress bar color. +// /// +// public PropertyColorProgress Color { get; set; } + +// /// +// /// Returns or sets the text color. +// /// +// public new PropertyColorText TextColor { get; set; } + +// /// +// /// Returns or sets the value. +// /// +// public int Value { get; set; } + +// /// +// /// Returns or sets the minimum value. +// /// +// public int Min { get; set; } + +// /// +// /// Returns or sets the maximum value. +// /// +// public int Max { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlProgressBar(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The value. +// public ControlProgressBar(string id, int value) +// : this(id) +// { +// Value = value; +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The value. +// public ControlProgressBar(string id, int value, int min = 0, int max = 100) +// : this(id) +// { +// Value = value; +// Min = min; +// Max = max; +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Min = 0; +// Max = 100; +// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Default); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// if (Format == TypeFormatProgress.Default) +// { +// return new HtmlElementFormProgress(Value + "%") +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role, +// Min = Min.ToString(), +// Max = Max.ToString(), +// Value = Value.ToString() +// }; +// } + +// var bar = new HtmlElementTextContentDiv(new HtmlText(Text)) +// { +// Role = "progressbar", +// Class = Css.Concatenate +// ( +// "progress-bar", +// Color?.ToClass(), +// TextColor?.ToClass(), +// Format.ToClass() +// ), +// Style = Css.Concatenate +// ( +// "width: " + Value + "%;", +// Color?.ToStyle(), +// TextColor?.ToStyle() +// ) +// }; +// bar.AddUserAttribute("aria-valuenow", Value.ToString()); +// bar.AddUserAttribute("aria-valuemin", Min.ToString()); +// bar.AddUserAttribute("aria-valuemax", Max.ToString()); + +// var html = new HtmlElementTextContentDiv(bar) +// { +// Id = Id, +// Role = Role, +// Class = Css.Concatenate +// ( +// "progress", +// GetClasses() +// ), +// Style = GetStyles() +// }; + +// return html; + +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs index 1301e839..4bbdbaf8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs @@ -1,244 +1,244 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlSplitButton : Control, IControlButton - { - /// - /// Returns or sets the background color. - /// - public new PropertyColorButton BackgroundColor - { - get => (PropertyColorButton)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); - } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the outline property - /// - public bool Outline { get; set; } - - /// - /// Returns or sets whether the button should take up the full width. - /// - public TypeBlockButton Block - { - get => (TypeBlockButton)GetProperty(TypeBlockButton.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the value. - /// - public string Value { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the activation status of the button. - /// - public TypeActive Active - { - get => (TypeActive)GetProperty(TypeActive.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets a modal dialogue. - /// - public PropertyModal Modal { get; set; } = new PropertyModal(); - - /// - /// Returns or sets the content. - /// - protected List Items { get; private set; } = new List(); - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlSplitButton(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlSplitButton(params IControlSplitButtonItem[] items) - : base(null) - { - Items.AddRange(items); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlSplitButton(string id, params IControlSplitButtonItem[] items) - : base(id) - { - Items.AddRange(items); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlSplitButton(string id, IEnumerable items) - : base(id) - { - Items.AddRange(items); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlSplitButton(IEnumerable items) - : base(null) - { - Items.AddRange(items); - - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Size = TypeSizeButton.Default; - //BackgroundColor = LayoutSchema.ButtonBackground; - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var button = new HtmlElementFieldButton() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles() - }; - - if (Icon != null && Icon.HasIcon) - { - button.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - button.Elements.Add(new HtmlText(Text)); - } - - if (Modal == null || Modal.Type == TypeModal.None) - { - - } - else if (Modal.Type == TypeModal.Form) - { - button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - } - else if (Modal.Type == TypeModal.Brwoser) - { - button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - } - else if (Modal.Type == TypeModal.Modal) - { - button.AddUserAttribute("data-bs-toggle", "modal"); - button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - } - - var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), - Style = GetStyles(), - DataToggle = "dropdown" - }; - dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); - dropdownButton.AddUserAttribute("aria-expanded", "false"); - - var dropdownElements = new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(context) : - new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } - ) - ) - { - Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" - }; - - var html = new HtmlElementTextContentDiv - ( - Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(context)) : button, - dropdownButton, - dropdownElements - ) - { - Class = Css.Concatenate - ( - "btn-group ", - Margin.ToClass(), - (Block == TypeBlockButton.Block ? "btn-block" : "") - ), - Role = Role - }; - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlSplitButton : Control, IControlButton +// { +// /// +// /// Returns or sets the background color. +// /// +// public new PropertyColorButton BackgroundColor +// { +// get => (PropertyColorButton)GetPropertyObject(); +// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); +// } + +// /// +// /// Returns or sets the size. +// /// +// public TypeSizeButton Size +// { +// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the outline property +// /// +// public bool Outline { get; set; } + +// /// +// /// Returns or sets whether the button should take up the full width. +// /// +// public TypeBlockButton Block +// { +// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the value. +// /// +// public string Value { get; set; } + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Returns or sets the activation status of the button. +// /// +// public TypeActive Active +// { +// get => (TypeActive)GetProperty(TypeActive.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets a modal dialogue. +// /// +// public PropertyModal Modal { get; set; } = new PropertyModal(); + +// /// +// /// Returns or sets the content. +// /// +// protected List Items { get; private set; } = new List(); + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlSplitButton(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlSplitButton(params IControlSplitButtonItem[] items) +// : base(null) +// { +// Items.AddRange(items); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlSplitButton(string id, params IControlSplitButtonItem[] items) +// : base(id) +// { +// Items.AddRange(items); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlSplitButton(string id, IEnumerable items) +// : base(id) +// { +// Items.AddRange(items); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlSplitButton(IEnumerable items) +// : base(null) +// { +// Items.AddRange(items); + +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Size = TypeSizeButton.Default; +// //BackgroundColor = LayoutSchema.ButtonBackground; +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var button = new HtmlElementFieldButton() +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), +// Style = GetStyles() +// }; + +// if (Icon != null && Icon.HasIcon) +// { +// button.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// button.Elements.Add(new HtmlText(Text)); +// } + +// if (Modal == null || Modal.Type == TypeModal.None) +// { + +// } +// else if (Modal.Type == TypeModal.Form) +// { +// button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// } +// else if (Modal.Type == TypeModal.Brwoser) +// { +// button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// } +// else if (Modal.Type == TypeModal.Modal) +// { +// button.AddUserAttribute("data-bs-toggle", "modal"); +// button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); +// } + +// var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), +// Style = GetStyles(), +// DataToggle = "dropdown" +// }; +// dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); +// dropdownButton.AddUserAttribute("aria-expanded", "false"); + +// var dropdownElements = new HtmlElementTextContentUl +// ( +// Items.Select +// ( +// x => +// x == null || x is ControlDropdownItemDivider || x is ControlLine ? +// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : +// x is ControlDropdownItemHeader ? +// x.Render(context) : +// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } +// ) +// ) +// { +// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" +// }; + +// var html = new HtmlElementTextContentDiv +// ( +// Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(context)) : button, +// dropdownButton, +// dropdownElements +// ) +// { +// Class = Css.Concatenate +// ( +// "btn-group ", +// Margin.ToClass(), +// (Block == TypeBlockButton.Block ? "btn-block" : "") +// ), +// Role = Role +// }; + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs index f8a5daca..a0b526a5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs @@ -1,43 +1,43 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlSplitButtonItemDivider : Control, IControlSplitButtonItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlSplitButtonItemDivider(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlSplitButtonItemDivider : Control, IControlSplitButtonItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlSplitButtonItemDivider(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("dropdown-divider", GetClasses()), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("dropdown-divider", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs index c024ad70..03c6e5f7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs @@ -1,59 +1,59 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlSplitButtonItemHeader : Control, IControlSplitButtonItem - { - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlSplitButtonItemHeader : Control, IControlSplitButtonItem +// { +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlSplitButtonItemHeader(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlSplitButtonItemHeader(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The text. - public ControlSplitButtonItemHeader(string id, string text) - : base(id) - { - Text = text; +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The text. +// public ControlSplitButtonItemHeader(string id, string text) +// : base(id) +// { +// Text = text; - Init(); - } +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementTextContentLi(new HtmlText(Text)) - { - Id = Id, - Class = Css.Concatenate("dropdown-header", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementTextContentLi(new HtmlText(Text)) +// { +// Id = Id, +// Class = Css.Concatenate("dropdown-header", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs index b8736d21..fdb15cc7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs @@ -1,35 +1,35 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlSplitButtonItemLink : ControlLink, IControlSplitButtonItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlSplitButtonItemLink(string id = null) - : base(id) - { - Init(); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlSplitButtonItemLink : ControlLink, IControlSplitButtonItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlSplitButtonItemLink(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return base.Render(context); - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return base.Render(context); +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs index a251dbe6..c87c0df8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs @@ -1,228 +1,228 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlSplitButtonLink : ControlSplitButton - { - /// - /// Returns or sets the target. - /// - public TypeTarget Target { get; set; } - - /// - /// Returns or sets the uri. - /// - public string Uri { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlSplitButtonLink(string id) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlSplitButtonLink(string id, params IControlSplitButtonItem[] content) - : base(id) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlSplitButtonLink(params IControlSplitButtonItem[] content) - : base(id: null) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlSplitButtonLink(string id, IEnumerable content) - : base(id) - { - Items.AddRange(content); - - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// The content of the html element. - public ControlSplitButtonLink(IEnumerable content) - : base(id: null) - { - Items.AddRange(content); - - Init(); - } - - /// - /// FΓΌgt ein neues Item hinzu - /// - /// - public void Add(IControlSplitButtonItem item) - { - Items.Add(item); - } - - /// - /// FΓΌgt ein neuen Seterator hinzu - /// - public void AddSeperator() - { - Items.Add(null); - } - - /// - /// FΓΌgt ein neuen Kopf hinzu - /// - /// Der Überschriftstext - public void AddHeader(string text) - { - Items.Add(new ControlSplitButtonItemHeader() { Text = text }); - } - - /// - /// Initialization - /// - private void Init() - { - Size = TypeSizeButton.Default; - Role = "button"; - } - - /// - /// FΓΌgt EintrΓ€ge hinzu - /// - /// The entries. welcher hinzugefΓΌgt werden sollen - public void Add(params IControlSplitButtonItem[] item) - { - Items.AddRange(item); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var button = new HtmlElementTextSemanticsA() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles(), - Target = Target, - Href = Uri?.ToString(), - OnClick = OnClick?.ToString() - }; - - if (Icon != null && Icon.HasIcon) - { - button.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - button.Elements.Add(new HtmlText(Text)); - } - - if (Modal == null || Modal.Type == TypeModal.None) - { - - } - else if (Modal.Type == TypeModal.Form) - { - button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - button.Href = "#"; - } - else if (Modal.Type == TypeModal.Brwoser) - { - button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{InternationalizationManager.I18N(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - button.Href = "#"; - } - else if (Modal.Type == TypeModal.Modal) - { - button.AddUserAttribute("data-bs-toggle", "modal"); - button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - } - - var dropdownButton = new HtmlElementTextSemanticsSpan(new HtmlElementTextSemanticsSpan() { Class = "caret" }) - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), - Style = GetStyles() - }; - dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); - dropdownButton.AddUserAttribute("aria-expanded", "false"); - - var dropdownElements = new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(context) : - new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } - ) - ) - { - Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" - }; - - var html = new HtmlElementTextContentDiv - ( - Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(context)) : button, - dropdownButton, - dropdownElements - ) - { - Class = Css.Concatenate - ( - "btn-group", - Margin.ToClass(), - (Block == TypeBlockButton.Block ? "btn-block" : "") - ), - Role = Role - }; - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlSplitButtonLink : ControlSplitButton +// { +// /// +// /// Returns or sets the target. +// /// +// public TypeTarget Target { get; set; } + +// /// +// /// Returns or sets the uri. +// /// +// public string Uri { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlSplitButtonLink(string id) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlSplitButtonLink(string id, params IControlSplitButtonItem[] content) +// : base(id) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlSplitButtonLink(params IControlSplitButtonItem[] content) +// : base(id: null) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlSplitButtonLink(string id, IEnumerable content) +// : base(id) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// The content of the html element. +// public ControlSplitButtonLink(IEnumerable content) +// : base(id: null) +// { +// Items.AddRange(content); + +// Init(); +// } + +// /// +// /// FΓΌgt ein neues Item hinzu +// /// +// /// +// public void Add(IControlSplitButtonItem item) +// { +// Items.Add(item); +// } + +// /// +// /// FΓΌgt ein neuen Seterator hinzu +// /// +// public void AddSeperator() +// { +// Items.Add(null); +// } + +// /// +// /// FΓΌgt ein neuen Kopf hinzu +// /// +// /// Der Überschriftstext +// public void AddHeader(string text) +// { +// Items.Add(new ControlSplitButtonItemHeader() { Text = text }); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Size = TypeSizeButton.Default; +// Role = "button"; +// } + +// /// +// /// FΓΌgt EintrΓ€ge hinzu +// /// +// /// The entries. welcher hinzugefΓΌgt werden sollen +// public void Add(params IControlSplitButtonItem[] item) +// { +// Items.AddRange(item); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var button = new HtmlElementTextSemanticsA() +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), +// Style = GetStyles(), +// Target = Target, +// Href = Uri?.ToString(), +// OnClick = OnClick?.ToString() +// }; + +// if (Icon != null && Icon.HasIcon) +// { +// button.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// button.Elements.Add(new HtmlText(Text)); +// } + +// if (Modal == null || Modal.Type == TypeModal.None) +// { + +// } +// else if (Modal.Type == TypeModal.Form) +// { +// button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// button.Href = "#"; +// } +// else if (Modal.Type == TypeModal.Brwoser) +// { +// button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; +// button.Href = "#"; +// } +// else if (Modal.Type == TypeModal.Modal) +// { +// button.AddUserAttribute("data-bs-toggle", "modal"); +// button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); +// } + +// var dropdownButton = new HtmlElementTextSemanticsSpan(new HtmlElementTextSemanticsSpan() { Class = "caret" }) +// { +// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", +// Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), +// Style = GetStyles() +// }; +// dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); +// dropdownButton.AddUserAttribute("aria-expanded", "false"); + +// var dropdownElements = new HtmlElementTextContentUl +// ( +// Items.Select +// ( +// x => +// x == null || x is ControlDropdownItemDivider || x is ControlLine ? +// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : +// x is ControlDropdownItemHeader ? +// x.Render(context) : +// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } +// ) +// ) +// { +// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" +// }; + +// var html = new HtmlElementTextContentDiv +// ( +// Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(context)) : button, +// dropdownButton, +// dropdownElements +// ) +// { +// Class = Css.Concatenate +// ( +// "btn-group", +// Margin.ToClass(), +// (Block == TypeBlockButton.Block ? "btn-block" : "") +// ), +// Role = Role +// }; + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTable.cs b/src/WebExpress.WebUI/WebControl/ControlTable.cs index 442ae586..d4ae73e1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTable.cs @@ -1,181 +1,181 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTable : Control - { - /// - /// Returns or sets the layout. der SpaltenΓΌberschrift - /// - public TypesLayoutTableRow ColumnLayout { get; set; } - - /// - /// Returns or sets the columns. - /// - public List Columns { get; private set; } - - /// - /// Returns or sets the rows. - /// - public List Rows { get; private set; } - - /// - /// Returns or sets the responsive property. - /// - public bool Responsive { get; set; } - - /// - /// Returns or sets the striped property. - /// - public bool Striped { get; set; } - - /// - /// Returns or sets the table to be rotated. - /// - public bool Reflow { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTable(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Striped = true; - Columns = new List(); - Rows = new List(); - } - - /// - /// Adds a column. - /// - /// The header of the column. - public virtual void AddColumn(string name) - { - Columns.Add(new ControlTableColumn(null) - { - Text = name - }); - } - - /// - /// Adds a column. - /// - /// The header of the column. - /// The icon of the column. - public virtual void AddColumn(string name, PropertyIcon icon) - { - Columns.Add(new ControlTableColumn(null) - { - Text = name, - Icon = icon - }); - } - - /// - /// Adds a column. - /// - /// The header of the column. - /// The icon of the column. - /// The layout of the column. - public virtual void AddColumn(string name, PropertyIcon icon, TypesLayoutTableRow layout) - { - Columns.Add(new ControlTableColumn(null) - { - Text = name, - Icon = icon, - Layout = layout - }); - } - - /// - /// Adds a row. - /// - /// The cells of the row. - public void AddRow(params Control[] cells) - { - var r = new ControlTableRow(null); - r.Cells.AddRange(cells); - - Rows.Add(r); - } - - /// - /// Adds a row. - /// - /// The cells of the row. - /// The css class. - public void AddRow(Control[] cells, string cssClass = null) - { - var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }) }; - r.Cells.AddRange(cells); - - Rows.Add(r); - } - - /// - /// Adds a row. - /// - /// The cells of the row. - /// The layout. - /// The css class. - public void AddRow(Control[] cells, TypesLayoutTableRow layout, string cssClass = null) - { - var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }), Layout = layout }; - r.Cells.AddRange(cells); - - Rows.Add(r); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Columns.ForEach(x => x.Layout = ColumnLayout); - var classes = Classes.ToList(); - classes.Add("table"); - - if (Striped) - { - classes.Add("table-striped"); - } - - if (Responsive) - { - classes.Add("table-responsive"); - } - - if (Reflow) - { - classes.Add("table-reflow"); - } - - var html = new HtmlElementTableTable() - { - Id = Id, - Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - - html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(context))); - html.Rows.AddRange(from x in Rows select x.Render(context) as HtmlElementTableTr); - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTable : Control +// { +// /// +// /// Returns or sets the layout. der SpaltenΓΌberschrift +// /// +// public TypesLayoutTableRow ColumnLayout { get; set; } + +// /// +// /// Returns or sets the columns. +// /// +// public List Columns { get; private set; } + +// /// +// /// Returns or sets the rows. +// /// +// public List Rows { get; private set; } + +// /// +// /// Returns or sets the responsive property. +// /// +// public bool Responsive { get; set; } + +// /// +// /// Returns or sets the striped property. +// /// +// public bool Striped { get; set; } + +// /// +// /// Returns or sets the table to be rotated. +// /// +// public bool Reflow { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTable(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Striped = true; +// Columns = new List(); +// Rows = new List(); +// } + +// /// +// /// Adds a column. +// /// +// /// The header of the column. +// public virtual void AddColumn(string name) +// { +// Columns.Add(new ControlTableColumn(null) +// { +// Text = name +// }); +// } + +// /// +// /// Adds a column. +// /// +// /// The header of the column. +// /// The icon of the column. +// public virtual void AddColumn(string name, PropertyIcon icon) +// { +// Columns.Add(new ControlTableColumn(null) +// { +// Text = name, +// Icon = icon +// }); +// } + +// /// +// /// Adds a column. +// /// +// /// The header of the column. +// /// The icon of the column. +// /// The layout of the column. +// public virtual void AddColumn(string name, PropertyIcon icon, TypesLayoutTableRow layout) +// { +// Columns.Add(new ControlTableColumn(null) +// { +// Text = name, +// Icon = icon, +// Layout = layout +// }); +// } + +// /// +// /// Adds a row. +// /// +// /// The cells of the row. +// public void AddRow(params Control[] cells) +// { +// var r = new ControlTableRow(null); +// r.Cells.AddRange(cells); + +// Rows.Add(r); +// } + +// /// +// /// Adds a row. +// /// +// /// The cells of the row. +// /// The css class. +// public void AddRow(Control[] cells, string cssClass = null) +// { +// var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }) }; +// r.Cells.AddRange(cells); + +// Rows.Add(r); +// } + +// /// +// /// Adds a row. +// /// +// /// The cells of the row. +// /// The layout. +// /// The css class. +// public void AddRow(Control[] cells, TypesLayoutTableRow layout, string cssClass = null) +// { +// var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }), Layout = layout }; +// r.Cells.AddRange(cells); + +// Rows.Add(r); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Columns.ForEach(x => x.Layout = ColumnLayout); +// var classes = Classes.ToList(); +// classes.Add("table"); + +// if (Striped) +// { +// classes.Add("table-striped"); +// } + +// if (Responsive) +// { +// classes.Add("table-responsive"); +// } + +// if (Reflow) +// { +// classes.Add("table-reflow"); +// } + +// var html = new HtmlElementTableTable() +// { +// Id = Id, +// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; + +// html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(context))); +// html.Rows.AddRange(from x in Rows select x.Render(context) as HtmlElementTableTr); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs index f02f5110..b188c1a7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs @@ -1,113 +1,113 @@ -ο»Ώusing System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώ//using System.Linq; +//using WebExpress.WebCore.Internationalization; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Zeile der Tabelle - /// - public class ControlTableColumn : Control - { - /// - /// Returns or sets the layout. - /// - public TypesLayoutTableRow Layout { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Zeile der Tabelle +// /// +// public class ControlTableColumn : Control +// { +// /// +// /// Returns or sets the layout. +// /// +// public TypesLayoutTableRow Layout { get; set; } - /// - /// Returns or sets the text. - /// - public string Text { get; set; } +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTableColumn(string id) - : base(id) - { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTableColumn(string id) +// : base(id) +// { - } +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var classes = Classes.ToList(); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var classes = Classes.ToList(); - switch (Layout) - { - case TypesLayoutTableRow.Primary: - classes.Add("table-primary"); - break; - case TypesLayoutTableRow.Secondary: - classes.Add("table-secondary"); - break; - case TypesLayoutTableRow.Success: - classes.Add("table-success"); - break; - case TypesLayoutTableRow.Info: - classes.Add("table-info"); - break; - case TypesLayoutTableRow.Warning: - classes.Add("table-warning"); - break; - case TypesLayoutTableRow.Danger: - classes.Add("table-danger"); - break; - case TypesLayoutTableRow.Light: - classes.Add("table-light"); - break; - case TypesLayoutTableRow.Dark: - classes.Add("table-dark"); - break; - } +// switch (Layout) +// { +// case TypesLayoutTableRow.Primary: +// classes.Add("table-primary"); +// break; +// case TypesLayoutTableRow.Secondary: +// classes.Add("table-secondary"); +// break; +// case TypesLayoutTableRow.Success: +// classes.Add("table-success"); +// break; +// case TypesLayoutTableRow.Info: +// classes.Add("table-info"); +// break; +// case TypesLayoutTableRow.Warning: +// classes.Add("table-warning"); +// break; +// case TypesLayoutTableRow.Danger: +// classes.Add("table-danger"); +// break; +// case TypesLayoutTableRow.Light: +// classes.Add("table-light"); +// break; +// case TypesLayoutTableRow.Dark: +// classes.Add("table-dark"); +// break; +// } - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; +// var html = new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; - if (Icon != null && Icon.HasIcon) - { - html.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } +// if (Icon != null && Icon.HasIcon) +// { +// html.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } - if (!string.IsNullOrWhiteSpace(Text)) - { - html.Elements.Add(new HtmlText(I18N(context.Culture, Text))); - } +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); +// } - return new HtmlElementTableTh(html) - { - Id = Id, - Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +// return new HtmlElementTableTh(html) +// { +// Id = Id, +// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs index 82ae554a..a02b49d9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs @@ -1,77 +1,77 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Zeile der Tabelle - /// - public class ControlTableRow : Control - { - /// - /// Returns or sets the layout. - /// - public TypesLayoutTableRow Layout { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Zeile der Tabelle +// /// +// public class ControlTableRow : Control +// { +// /// +// /// Returns or sets the layout. +// /// +// public TypesLayoutTableRow Layout { get; set; } - /// - /// Returns or set the cells. - /// - public List Cells { get; private set; } +// /// +// /// Returns or set the cells. +// /// +// public List Cells { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTableRow(string id = null) - : base(id) - { - Cells = new List(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTableRow(string id = null) +// : base(id) +// { +// Cells = new List(); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - switch (Layout) - { - case TypesLayoutTableRow.Primary: - Classes.Add("table-primary"); - break; - case TypesLayoutTableRow.Secondary: - Classes.Add("table-secondary"); - break; - case TypesLayoutTableRow.Success: - Classes.Add("table-success"); - break; - case TypesLayoutTableRow.Info: - Classes.Add("table-info"); - break; - case TypesLayoutTableRow.Warning: - Classes.Add("table-warning"); - break; - case TypesLayoutTableRow.Danger: - Classes.Add("table-danger"); - break; - case TypesLayoutTableRow.Light: - Classes.Add("table-light"); - break; - case TypesLayoutTableRow.Dark: - Classes.Add("table-dark"); - break; - } +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// switch (Layout) +// { +// case TypesLayoutTableRow.Primary: +// Classes.Add("table-primary"); +// break; +// case TypesLayoutTableRow.Secondary: +// Classes.Add("table-secondary"); +// break; +// case TypesLayoutTableRow.Success: +// Classes.Add("table-success"); +// break; +// case TypesLayoutTableRow.Info: +// Classes.Add("table-info"); +// break; +// case TypesLayoutTableRow.Warning: +// Classes.Add("table-warning"); +// break; +// case TypesLayoutTableRow.Danger: +// Classes.Add("table-danger"); +// break; +// case TypesLayoutTableRow.Light: +// Classes.Add("table-light"); +// break; +// case TypesLayoutTableRow.Dark: +// Classes.Add("table-dark"); +// break; +// } - return new HtmlElementTableTr(from c in Cells select new HtmlElementTableTd(c.Render(context))) - { - Id = Id, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +// return new HtmlElementTableTr(from c in Cells select new HtmlElementTableTd(c.Render(context))) +// { +// Id = Id, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTag.cs b/src/WebExpress.WebUI/WebControl/ControlTag.cs index 023b7799..502b4a31 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTag.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTag.cs @@ -1,165 +1,165 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTag : Control - { - /// - /// Returns or sets the layout. - /// - public TypeColorBackgroundBadge Layout { get; set; } - - /// - /// Return or specifies whether rounded corners should be used. - /// - public bool Pill { get; set; } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the content. - /// - protected List Items { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTag(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTag(string id, params Control[] content) - : this(id) - { - Items.AddRange(content); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTag(string id, IEnumerable content) - : this(id) - { - Items.AddRange(content); - } - - /// - /// Initialization - /// - private void Init() - { - Pill = true; - Items = new List(); - } - - /// - /// FΓΌgt ein neues Item hinzu - /// - /// - public void Add(Control item) - { - Items.Add(item); - } - - /// - /// FΓΌgt ein neuen Seterator hinzu - /// - public void AddSeperator() - { - Items.Add(null); - } - - /// - /// FΓΌgt ein neuen Kopf hinzu - /// - /// Der Überschriftstext - public void AddHeader(string text) - { - Items.Add(new ControlDropdownItemHeader() { Text = text }); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - - if (Pill) - { - Classes.Add("badge-pill"); - } - - if (Items.Count == 0) - { - return new HtmlElementTextSemanticsSpan(new HtmlText(Text)) - { - Class = Css.Concatenate("badge", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - - Classes.Add("btn"); - - var html = new HtmlElementTextSemanticsSpan() - { - Id = Id, - Class = "dropdown" - }; - - var tag = new HtmlElementTextSemanticsSpan - ( - new HtmlText(Text), new HtmlElementTextSemanticsSpan() - { - Class = "fas fa-caret-down" - } - ) - { - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role, - DataToggle = "dropdown" - }; - - html.Elements.Add(tag); - html.Elements.Add - ( - new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(context) : - new HtmlElementTextContentLi(x.Render(context).AddClass("dropdown-item")) { } - ) - ) - { - Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" - } - ); - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTag : Control +// { +// /// +// /// Returns or sets the layout. +// /// +// public TypeColorBackgroundBadge Layout { get; set; } + +// /// +// /// Return or specifies whether rounded corners should be used. +// /// +// public bool Pill { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the content. +// /// +// protected List Items { get; private set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTag(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTag(string id, params Control[] content) +// : this(id) +// { +// Items.AddRange(content); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTag(string id, IEnumerable content) +// : this(id) +// { +// Items.AddRange(content); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Pill = true; +// Items = new List(); +// } + +// /// +// /// FΓΌgt ein neues Item hinzu +// /// +// /// +// public void Add(Control item) +// { +// Items.Add(item); +// } + +// /// +// /// FΓΌgt ein neuen Seterator hinzu +// /// +// public void AddSeperator() +// { +// Items.Add(null); +// } + +// /// +// /// FΓΌgt ein neuen Kopf hinzu +// /// +// /// Der Überschriftstext +// public void AddHeader(string text) +// { +// Items.Add(new ControlDropdownItemHeader() { Text = text }); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { + +// if (Pill) +// { +// Classes.Add("badge-pill"); +// } + +// if (Items.Count == 0) +// { +// return new HtmlElementTextSemanticsSpan(new HtmlText(Text)) +// { +// Class = Css.Concatenate("badge", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } + +// Classes.Add("btn"); + +// var html = new HtmlElementTextSemanticsSpan() +// { +// Id = Id, +// Class = "dropdown" +// }; + +// var tag = new HtmlElementTextSemanticsSpan +// ( +// new HtmlText(Text), new HtmlElementTextSemanticsSpan() +// { +// Class = "fas fa-caret-down" +// } +// ) +// { +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role, +// DataToggle = "dropdown" +// }; + +// html.Elements.Add(tag); +// html.Elements.Add +// ( +// new HtmlElementTextContentUl +// ( +// Items.Select +// ( +// x => +// x == null ? +// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : +// x is ControlDropdownItemHeader ? +// x.Render(context) : +// new HtmlElementTextContentLi(x.Render(context).AddClass("dropdown-item")) { } +// ) +// ) +// { +// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" +// } +// ); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs index 8ca8e5ff..bb08c27c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs @@ -1,47 +1,47 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlTagCloud : Control - { - /// - /// Returns or sets the target uri. - /// - public Uri Uri { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTagCloud : Control +// { +// /// +// /// Returns or sets the target uri. +// /// +// public Uri Uri { get; set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTagCloud(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTagCloud(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - return new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - } - } -} +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// return new HtmlElementTextContentDiv() +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlText.cs b/src/WebExpress.WebUI/WebControl/ControlText.cs index 6426caff..22811dd1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlText.cs @@ -1,9 +1,12 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; -using static WebExpress.WebCore.Internationalization.InternationalizationManager; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Represents a text control with various formatting options. + /// public class ControlText : Control { /// @@ -16,8 +19,12 @@ public class ControlText : Control } /// - /// Liefert oder setzt das Format des Textes + /// Returns or sets the format of the text. /// + /// The format of the text. + /// + /// This property allows you to specify the format of the text, such as paragraph, italic, bold, underline, etc. + /// public TypeFormatText Format { get; set; } /// @@ -57,13 +64,13 @@ public ControlText(string id) } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) { - var text = I18N(context.Culture, Text); + var text = I18N.Translate(context?.Request.Culture, Text); HtmlElement html; switch (Format) diff --git a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs index 7022fe1a..d304c041 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs @@ -1,68 +1,68 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Stellt eine Timline (analog Facebook) bereit - /// - public class ControlTimeline : Control - { - /// - /// Liefert oder setzt die Timeline-EintrΓ€ge - /// - public List Items { get; protected set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Stellt eine Timline (analog Facebook) bereit +// /// +// public class ControlTimeline : Control +// { +// /// +// /// Liefert oder setzt die Timeline-EintrΓ€ge +// /// +// public List Items { get; protected set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTimeline(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTimeline(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTimeline(params ControlTimelineItem[] items) - : base(null) - { - Init(); +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTimeline(params ControlTimelineItem[] items) +// : base(null) +// { +// Init(); - Items.AddRange(items); - } +// Items.AddRange(items); +// } - /// - /// Initialization - /// - private void Init() - { - Items = new List(); - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// Items = new List(); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - Classes.Add("timeline"); +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// Classes.Add("timeline"); - var ul = new HtmlElementTextContentUl(Items.Select(x => new HtmlElementTextContentLi(x.Render(context)) { Class = "item" })) - { - Id = Id, - Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; +// var ul = new HtmlElementTextContentUl(Items.Select(x => new HtmlElementTextContentLi(x.Render(context)) { Class = "item" })) +// { +// Id = Id, +// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), +// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), +// Role = Role +// }; - return ul; - } - } -} +// return ul; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs index b3dfb4f3..84fe52ef 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs @@ -1,142 +1,142 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTimelineComment : Control - { - /// - /// Liefert oder setzt das Avatarbild - /// - public Uri Image { get; set; } - - /// - /// Returns or sets the name. des Users - /// - public string User { get; set; } - - /// - /// Liefert oder setzt den Zeitstempel - /// - public DateTime Timestamp { get; set; } - - /// - /// Returns or sets the text. - /// - public string Post { get; set; } - - /// - /// Liefert oder setzt die Anzahl der GefΓ€llt-mir-Angaben - /// - public int Likes { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTimelineComment(string id = null) - : base(id) - { - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var profile = new ControlAvatar() - { - User = User, - Image = Image - }; - var days = (DateTime.Now - Timestamp).Days; - - string timespan; - if (days == 1) - { - timespan = "vor ein Tag"; - } - else if (days < 1) - { - var hours = (DateTime.Now - Timestamp).Hours; - if (hours == 1) - { - timespan = "vor einer Stunde"; - } - else if (hours < 1) - { - var minutes = (DateTime.Now - Timestamp).Minutes; - - if (minutes == 1) - { - timespan = "vor einer Minute"; - } - else if (minutes < 1) - { - timespan = "gerade ebend"; - } - else - { - timespan = "vor " + minutes + " Minuten"; - } - } - else - { - timespan = "vor " + hours + " Stunden"; - } - } - else - { - timespan = "vor " + days + " Tagen"; - } - - var date = new ControlText() - { - Text = timespan, - Title = "Am " + Timestamp.ToShortDateString() + " um " + Timestamp.ToShortTimeString() + " Uhr", - Format = TypeFormatText.Span, - TextColor = new PropertyColorText(TypeColorText.Muted) - }; - - var header = new HtmlElementTextContentDiv(profile.Render(context), date.Render(context)) - { - Class = "header" - }; - - var body = new HtmlElementTextContentDiv(new HtmlText(Post)) - { - Class = "post" - }; - - var likeText = "GefΓ€llt mir" + (Likes > 0 ? " (" + Likes + ")" : string.Empty); - - var like = new ControlButtonLink() - { - Icon = new PropertyIcon(TypeIcon.ThumbsUp), - Text = likeText, - Uri = context.Uri, - Size = TypeSizeButton.Small, - BackgroundColor = new PropertyColorButton(TypeColorButton.Light), - Outline = true, - TextColor = new PropertyColorText(TypeColorText.Primary) - }; - - var option = new HtmlElementTextContentDiv(Likes > 0 ? like.Render(context) : null) - { - Class = "options" - }; - - var html = new HtmlElementTextContentDiv(header, body, option) - { - Class = Css.Concatenate("comment", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - return html; - } - } -} +ο»Ώ//using System; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTimelineComment : Control +// { +// /// +// /// Liefert oder setzt das Avatarbild +// /// +// public Uri Image { get; set; } + +// /// +// /// Returns or sets the name. des Users +// /// +// public string User { get; set; } + +// /// +// /// Liefert oder setzt den Zeitstempel +// /// +// public DateTime Timestamp { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Post { get; set; } + +// /// +// /// Liefert oder setzt die Anzahl der GefΓ€llt-mir-Angaben +// /// +// public int Likes { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTimelineComment(string id = null) +// : base(id) +// { +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var profile = new ControlAvatar() +// { +// User = User, +// Image = Image +// }; +// var days = (DateTime.Now - Timestamp).Days; + +// string timespan; +// if (days == 1) +// { +// timespan = "vor ein Tag"; +// } +// else if (days < 1) +// { +// var hours = (DateTime.Now - Timestamp).Hours; +// if (hours == 1) +// { +// timespan = "vor einer Stunde"; +// } +// else if (hours < 1) +// { +// var minutes = (DateTime.Now - Timestamp).Minutes; + +// if (minutes == 1) +// { +// timespan = "vor einer Minute"; +// } +// else if (minutes < 1) +// { +// timespan = "gerade ebend"; +// } +// else +// { +// timespan = "vor " + minutes + " Minuten"; +// } +// } +// else +// { +// timespan = "vor " + hours + " Stunden"; +// } +// } +// else +// { +// timespan = "vor " + days + " Tagen"; +// } + +// var date = new ControlText() +// { +// Text = timespan, +// Title = "Am " + Timestamp.ToShortDateString() + " um " + Timestamp.ToShortTimeString() + " Uhr", +// Format = TypeFormatText.Span, +// TextColor = new PropertyColorText(TypeColorText.Muted) +// }; + +// var header = new HtmlElementTextContentDiv(profile.Render(context), date.Render(context)) +// { +// Class = "header" +// }; + +// var body = new HtmlElementTextContentDiv(new HtmlText(Post)) +// { +// Class = "post" +// }; + +// var likeText = "GefΓ€llt mir" + (Likes > 0 ? " (" + Likes + ")" : string.Empty); + +// var like = new ControlButtonLink() +// { +// Icon = new PropertyIcon(TypeIcon.ThumbsUp), +// Text = likeText, +// Uri = context.Uri, +// Size = TypeSizeButton.Small, +// BackgroundColor = new PropertyColorButton(TypeColorButton.Light), +// Outline = true, +// TextColor = new PropertyColorText(TypeColorText.Primary) +// }; + +// var option = new HtmlElementTextContentDiv(Likes > 0 ? like.Render(context) : null) +// { +// Class = "options" +// }; + +// var html = new HtmlElementTextContentDiv(header, body, option) +// { +// Class = Css.Concatenate("comment", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs index 946de925..d390221b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs @@ -1,208 +1,208 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTimelineItem : Control - { - /// - /// Returns or sets the name. - /// - public string Name { get; set; } - - /// - /// Returns or sets the image. - /// - public Uri Image { get; set; } - - /// - /// Returns or sets the user name. - /// - public string User { get; set; } - - /// - /// Liefert oder setzt die Aktion des Eintrages - /// - public string Action { get; set; } - - /// - /// Liefert oder setzt den Zeitstempel - /// - public DateTime Timestamp { get; set; } - - /// - /// Returns or sets the text. - /// - public string Post { get; set; } - - /// - /// Liefert oder setzt die Kommentare - /// - public List Comments { get; private set; } - - /// - /// Liefert oder setzt die Anzahl der GefΓ€llt-mir-Angaben - /// - public int Likes { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTimelineItem(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - Comments = new List(); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var profile = new ControlAvatar() - { - User = User, - Image = Image - }; - - var timespan = string.Empty; - var days = (DateTime.Now - Timestamp).Days; - if (days == 1) - { - timespan = "vor ein Tag"; - } - else if (days < 1) - { - var hours = (DateTime.Now - Timestamp).Hours; - if (hours == 1) - { - timespan = "vor einer Stunde"; - } - else if (hours < 1) - { - var minutes = (DateTime.Now - Timestamp).Minutes; - - if (minutes == 1) - { - timespan = "vor einer Minute"; - } - else if (minutes < 1) - { - timespan = "gerade ebend"; - } - else - { - timespan = "vor " + minutes + " Minuten"; - } - } - else - { - timespan = "vor " + hours + " Stunden"; - } - } - else - { - timespan = "vor " + days + " Tagen"; - } - - var date = new ControlText() - { - Text = timespan, - Title = "Am " + Timestamp.ToShortDateString() + " um " + Timestamp.ToShortTimeString() + " Uhr", - Format = TypeFormatText.Span, - TextColor = new PropertyColorText(TypeColorText.Muted) - }; - - var headerText = new HtmlElementTextContentP - ( - new ControlText() - { - Text = Action, - TextColor = new PropertyColorText(TypeColorText.Info), - Format = TypeFormatText.Span - }.Render(context), - date.Render(context) - ); - - var setting = new ControlDropdown() - { - //Icon = new PropertyIcon(TypeIcon.Cog), - BackgroundColor = new PropertyColorButton(TypeColorButton.Light), - HorizontalAlignment = TypeHorizontalAlignment.Right, - Size = TypeSizeButton.Small - }; - setting.Add(new ControlDropdownItemLink() - { - Text = "LΓΆschen", - Icon = new PropertyIcon(TypeIcon.TrashAlt), - TextColor = new PropertyColorText(TypeColorText.Danger), - Uri = context.Uri - }); - - var header = new HtmlElementTextContentDiv(setting.Render(context), profile.Render(context), headerText) - { - Class = "header" - }; - - var body = new HtmlElementTextContentDiv(new HtmlText(Post)) - { - Class = Css.Concatenate("post", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - var likeText = "GefΓ€llt mir" + (Likes > 0 ? " (" + Likes + ")" : string.Empty); - var like = new ControlButtonLink() - { - Icon = new PropertyIcon(TypeIcon.ThumbsUp), - Text = likeText, - Uri = context.Request.Uri?.ToString(), - Size = TypeSizeButton.Small, - BackgroundColor = new PropertyColorButton(TypeColorButton.Light), - Outline = true, - TextColor = new PropertyColorText(TypeColorText.Primary) - }; - - var option = new HtmlElementTextContentDiv(like.Render(context)) - { - Class = "options" - }; - - var html = new HtmlList(header, body, option); - - html.Elements.AddRange(from x in Comments select x.Render(context)); - - var form = new ControlForm() - { - Name = !string.IsNullOrWhiteSpace(Name) ? Name : "form" - }; - - form.AddPrimaryButton(new ControlFormItemButtonSubmit("") - { - Icon = new PropertyIcon(TypeIcon.PaperPlane), - Outline = true, - Size = TypeSizeButton.Small - }); - - form.Add(new ControlFormItemInputTextBox() { Format = TypesEditTextFormat.Multiline, Placeholder = "Kommentieren..." }); - - html.Elements.Add(form.Render(context)); - - return html; - } - } -} +ο»Ώ//using System; +//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTimelineItem : Control +// { +// /// +// /// Returns or sets the name. +// /// +// public string Name { get; set; } + +// /// +// /// Returns or sets the image. +// /// +// public Uri Image { get; set; } + +// /// +// /// Returns or sets the user name. +// /// +// public string User { get; set; } + +// /// +// /// Liefert oder setzt die Aktion des Eintrages +// /// +// public string Action { get; set; } + +// /// +// /// Liefert oder setzt den Zeitstempel +// /// +// public DateTime Timestamp { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Post { get; set; } + +// /// +// /// Liefert oder setzt die Kommentare +// /// +// public List Comments { get; private set; } + +// /// +// /// Liefert oder setzt die Anzahl der GefΓ€llt-mir-Angaben +// /// +// public int Likes { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTimelineItem(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// Comments = new List(); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var profile = new ControlAvatar() +// { +// User = User, +// Image = Image +// }; + +// var timespan = string.Empty; +// var days = (DateTime.Now - Timestamp).Days; +// if (days == 1) +// { +// timespan = "vor ein Tag"; +// } +// else if (days < 1) +// { +// var hours = (DateTime.Now - Timestamp).Hours; +// if (hours == 1) +// { +// timespan = "vor einer Stunde"; +// } +// else if (hours < 1) +// { +// var minutes = (DateTime.Now - Timestamp).Minutes; + +// if (minutes == 1) +// { +// timespan = "vor einer Minute"; +// } +// else if (minutes < 1) +// { +// timespan = "gerade ebend"; +// } +// else +// { +// timespan = "vor " + minutes + " Minuten"; +// } +// } +// else +// { +// timespan = "vor " + hours + " Stunden"; +// } +// } +// else +// { +// timespan = "vor " + days + " Tagen"; +// } + +// var date = new ControlText() +// { +// Text = timespan, +// Title = "Am " + Timestamp.ToShortDateString() + " um " + Timestamp.ToShortTimeString() + " Uhr", +// Format = TypeFormatText.Span, +// TextColor = new PropertyColorText(TypeColorText.Muted) +// }; + +// var headerText = new HtmlElementTextContentP +// ( +// new ControlText() +// { +// Text = Action, +// TextColor = new PropertyColorText(TypeColorText.Info), +// Format = TypeFormatText.Span +// }.Render(context), +// date.Render(context) +// ); + +// var setting = new ControlDropdown() +// { +// //Icon = new PropertyIcon(TypeIcon.Cog), +// BackgroundColor = new PropertyColorButton(TypeColorButton.Light), +// HorizontalAlignment = TypeHorizontalAlignment.Right, +// Size = TypeSizeButton.Small +// }; +// setting.Add(new ControlDropdownItemLink() +// { +// Text = "LΓΆschen", +// Icon = new PropertyIcon(TypeIcon.TrashAlt), +// TextColor = new PropertyColorText(TypeColorText.Danger), +// Uri = context.Uri +// }); + +// var header = new HtmlElementTextContentDiv(setting.Render(context), profile.Render(context), headerText) +// { +// Class = "header" +// }; + +// var body = new HtmlElementTextContentDiv(new HtmlText(Post)) +// { +// Class = Css.Concatenate("post", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// var likeText = "GefΓ€llt mir" + (Likes > 0 ? " (" + Likes + ")" : string.Empty); +// var like = new ControlButtonLink() +// { +// Icon = new PropertyIcon(TypeIcon.ThumbsUp), +// Text = likeText, +// Uri = context.Request.Uri?.ToString(), +// Size = TypeSizeButton.Small, +// BackgroundColor = new PropertyColorButton(TypeColorButton.Light), +// Outline = true, +// TextColor = new PropertyColorText(TypeColorText.Primary) +// }; + +// var option = new HtmlElementTextContentDiv(like.Render(context)) +// { +// Class = "options" +// }; + +// var html = new HtmlList(header, body, option); + +// html.Elements.AddRange(from x in Comments select x.Render(context)); + +// var form = new ControlForm() +// { +// Name = !string.IsNullOrWhiteSpace(Name) ? Name : "form" +// }; + +// form.AddPrimaryButton(new ControlFormItemButtonSubmit("") +// { +// Icon = new PropertyIcon(TypeIcon.PaperPlane), +// Outline = true, +// Size = TypeSizeButton.Small +// }); + +// form.Add(new ControlFormItemInputTextBox() { Format = TypesEditTextFormat.Multiline, Placeholder = "Kommentieren..." }); + +// html.Elements.Add(form.Render(context)); + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs index 5d377767..6f737420 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs @@ -1,129 +1,129 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class ControlToolbar : Control - { - /// - /// Die horizontale Anordnung - /// - public virtual TypeOrientationToolBar Orientation - { - get => (TypeOrientationToolBar)GetProperty(TypeOrientationToolBar.Default); - set => SetProperty(value, () => value.ToClass()); - } +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlToolbar : Control +// { +// /// +// /// Die horizontale Anordnung +// /// +// public virtual TypeOrientationToolBar Orientation +// { +// get => (TypeOrientationToolBar)GetProperty(TypeOrientationToolBar.Default); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Die fixierte Anordnung - /// - public virtual TypeFixed Fixed - { - get => (TypeFixed)GetProperty(TypeFixed.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Die fixierte Anordnung +// /// +// public virtual TypeFixed Fixed +// { +// get => (TypeFixed)GetProperty(TypeFixed.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Fixiert die Anordnung, wenn sich die Toolbar am oberen Rand befindet - /// - public virtual TypeSticky Sticky - { - get => (TypeSticky)GetProperty(TypeSticky.None); - set => SetProperty(value, () => value.ToClass()); - } +// /// +// /// Fixiert die Anordnung, wenn sich die Toolbar am oberen Rand befindet +// /// +// public virtual TypeSticky Sticky +// { +// get => (TypeSticky)GetProperty(TypeSticky.None); +// set => SetProperty(value, () => value.ToClass()); +// } - /// - /// Returns or sets the content. - /// - public List Items { get; private set; } = new List(); +// /// +// /// Returns or sets the content. +// /// +// public List Items { get; private set; } = new List(); - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlToolbar(string id = null) - : base(id) - { - Init(); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlToolbar(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// Die Toolitems - public ControlToolbar(string id = null, params IControlToolBarItem[] items) - : this(id) - { - Add(items); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// Die Toolitems +// public ControlToolbar(string id = null, params IControlToolBarItem[] items) +// : this(id) +// { +// Add(items); +// } - /// - /// Initializes a new instance of the class. - /// - /// Die Toolitems - public ControlToolbar(params IControlToolBarItem[] items) - : this((string)null) - { - Add(items); - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// Die Toolitems +// public ControlToolbar(params IControlToolBarItem[] items) +// : this((string)null) +// { +// Add(items); +// } - /// - /// Initialization - /// - private void Init() - { - BackgroundColor = new PropertyColorBackground(TypeColorBackground.Warning); - Orientation = TypeOrientationToolBar.Default; - Padding = new PropertySpacingPadding(PropertySpacing.Space.Two, PropertySpacing.Space.None); - } +// /// +// /// Initialization +// /// +// private void Init() +// { +// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Warning); +// Orientation = TypeOrientationToolBar.Default; +// Padding = new PropertySpacingPadding(PropertySpacing.Space.Two, PropertySpacing.Space.None); +// } - /// - /// FΓΌgt EintrΓ€ge hinzu - /// - /// The entries. welcher hinzugefΓΌgt werden sollen - public void Add(params IControlToolBarItem[] item) - { - Items.AddRange(item); - } +// /// +// /// FΓΌgt EintrΓ€ge hinzu +// /// +// /// The entries. welcher hinzugefΓΌgt werden sollen +// public void Add(params IControlToolBarItem[] item) +// { +// Items.AddRange(item); +// } - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var html = new HtmlElementSectionNav() - { - Id = Id, - Class = GetClasses(), - Style = GetStyles(), - Role = Role - }; +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var html = new HtmlElementSectionNav() +// { +// Id = Id, +// Class = GetClasses(), +// Style = GetStyles(), +// Role = Role +// }; - html.Elements.Add - ( - new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(context) : - new HtmlElementTextContentLi(x.Render(context)) { Class = "nav-item" } - ) - ) - { - Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "" : "navbar-nav" - } - ); +// html.Elements.Add +// ( +// new HtmlElementTextContentUl +// ( +// Items.Select +// ( +// x => +// x == null || x is ControlDropdownItemDivider || x is ControlLine ? +// new HtmlElementTextContentLi() { Class = "divider", Inline = true } : +// x is ControlDropdownItemHeader ? +// x.Render(context) : +// new HtmlElementTextContentLi(x.Render(context)) { Class = "nav-item" } +// ) +// ) +// { +// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "" : "navbar-nav" +// } +// ); - return html; - } - } -} +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs index 4895d228..d6cfd09c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs @@ -1,25 +1,25 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlToolBarItemButton : ControlLink, IControlToolBarItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlToolBarItemButton(string id = null) - : base(id) - { - Init(); - } +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlToolBarItemButton : ControlLink, IControlToolBarItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlToolBarItemButton(string id = null) +// : base(id) +// { +// Init(); +// } - /// - /// Initialization - /// - private void Init() - { - Classes.Add("nav-link"); +// /// +// /// Initialization +// /// +// private void Init() +// { +// Classes.Add("nav-link"); - //TextColor = LayoutSchema.ToolbarLink; - } - } -} +// //TextColor = LayoutSchema.ToolbarLink; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs index 37af56e4..1ff6b83c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs @@ -1,15 +1,15 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ControlToolBarItemSeperator : ControlLine, IControlToolBarItem - { - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlToolBarItemSeperator(string id = null) - : base(id) - { +ο»Ώ//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlToolBarItemSeperator : ControlLine, IControlToolBarItem +// { +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlToolBarItemSeperator(string id = null) +// : base(id) +// { - } - } -} +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTree.cs b/src/WebExpress.WebUI/WebControl/ControlTree.cs index 0a1f3d3a..5b189d08 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTree.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTree.cs @@ -1,153 +1,153 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTree : Control - { - /// - /// Returns or sets the layout. - /// - public TypeLayoutTree Layout - { - get => (TypeLayoutTree)GetProperty(TypeLayoutTree.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Liefert oder setzt die Baumknoten - /// - public List Items { get; private set; } = new List(); - - /// - /// Bestimm, ob es sich um eine sotrierte oder unsortierte Liste handelt - /// - public bool Sorted { get; set; } - - /// - /// Zeigt einen Rahmen an oder keinen - /// - public bool ShowBorder { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTree(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// Die ListeneintrΓ€ge - public ControlTree(string id, params ControlTreeItem[] items) - : base(id) - { - Items.AddRange(items); - } - - /// - /// Initializes a new instance of the class. - /// - /// Die ListeneintrΓ€ge - public ControlTree(params ControlTreeItem[] items) - : this(null, items) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id. - /// Die ListeneintrΓ€ge - public ControlTree(string id, List items) - : base(id) - { - Items = items; - } - - /// - /// Initializes a new instance of the class. - /// - /// Die ListeneintrΓ€ge - public ControlTree(List items) - : this(null, items) - { - } - - /// - /// Initialization - /// - private void Init() - { - ShowBorder = true; - } - - /// - /// FΓΌgt ListeneintrΓ€ge hinzu - /// - /// Die ListeneintrΓ€ge - public void Add(IEnumerable items) - { - Items.AddRange(items); - } - - /// - /// FΓΌgt ListeneintrΓ€ge hinzu - /// - /// Der Listeneintrag - public void Add(ControlTreeItem item) - { - Items.Add(item); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var items = (from x in Items select x.Render(context)).ToList(); - - switch (Layout) - { - case TypeLayoutTree.Horizontal: - case TypeLayoutTree.Flush: - case TypeLayoutTree.Group: - items.ForEach(x => x.AddClass("list-group-item")); - break; - } - - var html = new HtmlElementTextContentUl(items) - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - if (Layout == TypeLayoutTree.TreeView) - { - context.VisualTree.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); - for (var i = 0; i < toggler.length; i++) - { - toggler[i].addEventListener(""click"", function() { - this.parentElement.parentElement.querySelector("".tree-treeview-node"").classList.toggle(""tree-node-hide""); - this.classList.toggle(""tree-treeview-angle-down""); - - }); - } - "); - } - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTree : Control +// { +// /// +// /// Returns or sets the layout. +// /// +// public TypeLayoutTree Layout +// { +// get => (TypeLayoutTree)GetProperty(TypeLayoutTree.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Liefert oder setzt die Baumknoten +// /// +// public List Items { get; private set; } = new List(); + +// /// +// /// Bestimm, ob es sich um eine sotrierte oder unsortierte Liste handelt +// /// +// public bool Sorted { get; set; } + +// /// +// /// Zeigt einen Rahmen an oder keinen +// /// +// public bool ShowBorder { get; set; } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTree(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// Die ListeneintrΓ€ge +// public ControlTree(string id, params ControlTreeItem[] items) +// : base(id) +// { +// Items.AddRange(items); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// Die ListeneintrΓ€ge +// public ControlTree(params ControlTreeItem[] items) +// : this(null, items) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id. +// /// Die ListeneintrΓ€ge +// public ControlTree(string id, List items) +// : base(id) +// { +// Items = items; +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// Die ListeneintrΓ€ge +// public ControlTree(List items) +// : this(null, items) +// { +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// ShowBorder = true; +// } + +// /// +// /// FΓΌgt ListeneintrΓ€ge hinzu +// /// +// /// Die ListeneintrΓ€ge +// public void Add(IEnumerable items) +// { +// Items.AddRange(items); +// } + +// /// +// /// FΓΌgt ListeneintrΓ€ge hinzu +// /// +// /// Der Listeneintrag +// public void Add(ControlTreeItem item) +// { +// Items.Add(item); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var items = (from x in Items select x.Render(context)).ToList(); + +// switch (Layout) +// { +// case TypeLayoutTree.Horizontal: +// case TypeLayoutTree.Flush: +// case TypeLayoutTree.Group: +// items.ForEach(x => x.AddClass("list-group-item")); +// break; +// } + +// var html = new HtmlElementTextContentUl(items) +// { +// Id = Id, +// Class = Css.Concatenate("", GetClasses()), +// Style = GetStyles(), +// Role = Role +// }; + +// if (Layout == TypeLayoutTree.TreeView) +// { +// context.VisualTree.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); +// for (var i = 0; i < toggler.length; i++) +// { +// toggler[i].addEventListener(""click"", function() { +// this.parentElement.parentElement.querySelector("".tree-treeview-node"").classList.toggle(""tree-node-hide""); +// this.classList.toggle(""tree-treeview-angle-down""); + +// }); +// } +// "); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs index 78fe4310..fc80a929 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs @@ -1,186 +1,186 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTreeItem : Control - { - /// - /// Returns or sets the content. - /// - public List Content { get; private set; } = new List(); - - /// - /// Liefert oder setzt die Kinderknoten - /// - public List Children { get; private set; } = new List(); - - /// - /// Ermittelt ob ein untergeordneter Baumknoten aktiv ist - /// - public bool IsAnyChildrenActive - { - get - { - if (Active == TypeActive.Active) return true; - - return Children.Where(x => x.IsAnyChildrenActive).Any(); - } - } - - /// - /// Liefert oder setzt die AtivitΓ€tsstatus des Listenelements - /// - public TypeActive Active - { - get => (TypeActive)GetProperty(TypeActive.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the layout. - /// - public TypeLayoutTreeItem Layout - { - get => (TypeLayoutTreeItem)GetProperty(TypeLayoutTreeItem.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Bestimmt, ob die Kinknoten angezeigt werden oder nicht - /// - public TypeExpandTree Expand - { - get => (TypeExpandTree)GetProperty(TypeExpandTree.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTreeItem(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTreeItem(string id, params Control[] content) - : this(id) - { - Content.AddRange(content.Where(x => !(x is ControlTreeItem))); - Children.AddRange(content.Where(x => x is ControlTreeItem).Select(x => x as ControlTreeItem)); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlTreeItem(params Control[] content) - : this(null, content) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTreeItem(string id, List content) - : this(id, content.ToArray()) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlTreeItem(List content) - : this(null, content) - { - } - - /// - /// Initialization - /// - private void Init() - { - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var content = from x in Content select x.Render(context); - var container = default(HtmlElementTextContentDiv); - - if (Layout == TypeLayoutTreeItem.TreeView) - { - var expander = new HtmlElementTextSemanticsSpan - { - Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") - }; - - if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) - { - expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); - } - - container = new HtmlElementTextContentDiv(expander, content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()) - { - Class = Css.Concatenate("tree-treeview-container") - }; - } - else - { - container = new HtmlElementTextContentDiv(content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()); - } - - var html = new HtmlElementTextContentLi(container) - { - Id = Id, - Class = Css.Concatenate(Active.ToClass()), - Style = GetStyles(), - Role = Role - }; - - if (Children.Count > 0) - { - var items = (from x in Children select x.Render(context)).ToList(); - - switch (Layout) - { - case TypeLayoutTreeItem.Horizontal: - case TypeLayoutTreeItem.Flush: - case TypeLayoutTreeItem.Group: - items.ForEach(x => x.AddClass("list-group-item")); - break; - } - - var ul = new HtmlElementTextContentUl(items) - { - Class = Css.Concatenate(Layout switch - { - TypeLayoutTreeItem.TreeView => "tree-treeview-node", - TypeLayoutTreeItem.Simple => "tree-simple-node", - _ => Layout.ToClass() - }, Expand.ToClass()) - }; - - html.Elements.Add(ul); - } - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTreeItem : Control +// { +// /// +// /// Returns or sets the content. +// /// +// public List Content { get; private set; } = new List(); + +// /// +// /// Liefert oder setzt die Kinderknoten +// /// +// public List Children { get; private set; } = new List(); + +// /// +// /// Ermittelt ob ein untergeordneter Baumknoten aktiv ist +// /// +// public bool IsAnyChildrenActive +// { +// get +// { +// if (Active == TypeActive.Active) return true; + +// return Children.Where(x => x.IsAnyChildrenActive).Any(); +// } +// } + +// /// +// /// Liefert oder setzt die AtivitΓ€tsstatus des Listenelements +// /// +// public TypeActive Active +// { +// get => (TypeActive)GetProperty(TypeActive.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Returns or sets the layout. +// /// +// public TypeLayoutTreeItem Layout +// { +// get => (TypeLayoutTreeItem)GetProperty(TypeLayoutTreeItem.Default); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Bestimmt, ob die Kinknoten angezeigt werden oder nicht +// /// +// public TypeExpandTree Expand +// { +// get => (TypeExpandTree)GetProperty(TypeExpandTree.None); +// set => SetProperty(value, () => value.ToClass()); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTreeItem(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTreeItem(string id, params Control[] content) +// : this(id) +// { +// Content.AddRange(content.Where(x => !(x is ControlTreeItem))); +// Children.AddRange(content.Where(x => x is ControlTreeItem).Select(x => x as ControlTreeItem)); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlTreeItem(params Control[] content) +// : this(null, content) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTreeItem(string id, List content) +// : this(id, content.ToArray()) +// { +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlTreeItem(List content) +// : this(null, content) +// { +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var content = from x in Content select x.Render(context); +// var container = default(HtmlElementTextContentDiv); + +// if (Layout == TypeLayoutTreeItem.TreeView) +// { +// var expander = new HtmlElementTextSemanticsSpan +// { +// Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") +// }; + +// if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) +// { +// expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); +// } + +// container = new HtmlElementTextContentDiv(expander, content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()) +// { +// Class = Css.Concatenate("tree-treeview-container") +// }; +// } +// else +// { +// container = new HtmlElementTextContentDiv(content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()); +// } + +// var html = new HtmlElementTextContentLi(container) +// { +// Id = Id, +// Class = Css.Concatenate(Active.ToClass()), +// Style = GetStyles(), +// Role = Role +// }; + +// if (Children.Count > 0) +// { +// var items = (from x in Children select x.Render(context)).ToList(); + +// switch (Layout) +// { +// case TypeLayoutTreeItem.Horizontal: +// case TypeLayoutTreeItem.Flush: +// case TypeLayoutTreeItem.Group: +// items.ForEach(x => x.AddClass("list-group-item")); +// break; +// } + +// var ul = new HtmlElementTextContentUl(items) +// { +// Class = Css.Concatenate(Layout switch +// { +// TypeLayoutTreeItem.TreeView => "tree-treeview-node", +// TypeLayoutTreeItem.Simple => "tree-simple-node", +// _ => Layout.ToClass() +// }, Expand.ToClass()) +// }; + +// html.Elements.Add(ul); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs index 47283c4e..b43f9a0e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs @@ -1,240 +1,240 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - public class ControlTreeItemLink : ControlTreeItem - { - /// - /// Returns or sets the target uri. - /// - public string Uri { get; set; } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the target. - /// - public TypeTarget Target { get; set; } - - /// - /// Returns or sets the tooltip. - /// - public string Title { get; set; } - - /// - /// Returns or sets a tooltip text. - /// - public string Tooltip { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Liefert oder setzt die fΓΌr den Link gΓΌltigen Parameter - /// - public List Params { get; set; } - - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlTreeItemLink(string id = null) - : base(id) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTreeItemLink(string id, params Control[] content) - : base(id, content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlTreeItemLink(params Control[] content) - : base(content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The content of the html element. - public ControlTreeItemLink(string id, List content) - : base(id, content) - { - Init(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlTreeItemLink(List content) - : base(content) - { - Init(); - } - - /// - /// Initialization - /// - private void Init() - { - } - - /// - /// Returns all local and temporary parameters. - /// - /// The context in which the control is rendered. - /// The parameters. - public string GetParams(IPage page) - { - var dict = new Dictionary(); - - // Übernahme der Parameter des Link - if (Params != null) - { - foreach (var v in Params) - { - if (string.IsNullOrWhiteSpace(Uri?.ToString())) - { - if (!dict.ContainsKey(v.Key.ToLower())) - { - dict.Add(v.Key.ToLower(), v); - } - else - { - dict[v.Key.ToLower()] = v; - } - } - } - } - - return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); - } - - /// - /// Convert to html. - /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(RenderContext context) - { - var param = GetParams(context?.Page); - - var link = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) - { - Id = Id, - Class = Css.Concatenate("link tree-link", Active == TypeActive.Active ? "tree-link-active" : ""), - Role = Role, - Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), - Target = Target, - Title = Title, - OnClick = OnClick?.ToString() - }; - - if (Icon != null && Icon.HasIcon) - { - link.Elements.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - link.Elements.Add(new HtmlText(Text)); - } - - if (!string.IsNullOrWhiteSpace(Tooltip)) - { - link.AddUserAttribute("data-toggle", "tooltip"); - } - - var expander = new HtmlElementTextSemanticsSpan - { - Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") - }; - - if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) - { - expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); - } - var container = new HtmlElementTextContentDiv(expander, link) - { - Class = Css.Concatenate("tree-treeview-container") - }; - - var html = new HtmlElementTextContentLi(Layout == TypeLayoutTreeItem.TreeView ? container : link) - { - Id = Id, - Class = Css.Concatenate(Layout switch - { - TypeLayoutTreeItem.Group => "list-group-item-action", - TypeLayoutTreeItem.Flush => "list-group-item-action", - TypeLayoutTreeItem.Horizontal => "list-group-item-action", - TypeLayoutTreeItem.TreeView => "tree-item", - _ => "" - }, Active.ToClass()), - Style = GetStyles(), - Role = Role - }; - - if (Children.Count > 0) - { - var items = (from x in Children select x.Render(context)).ToList(); - var ul = new HtmlElementTextContentUl(items) - { - Class = Css.Concatenate(Layout switch - { - TypeLayoutTreeItem.TreeView => "tree-treeview-node", - TypeLayoutTreeItem.Simple => "tree-simple-node", - _ => Layout.ToClass() - }, Expand.ToClass()) - }; - - switch (Layout) - { - case TypeLayoutTreeItem.Horizontal: - case TypeLayoutTreeItem.Flush: - case TypeLayoutTreeItem.Group: - items.ForEach(x => x.AddClass("list-group-item")); - break; - } - - html.Elements.Add(ul); - } - - return html; - } - } -} +ο»Ώ//using System.Collections.Generic; +//using System.Linq; +//using WebExpress.WebCore.WebHtml; +//using WebExpress.WebCore.WebMessage; +//using WebExpress.WebCore.WebPage; + +//namespace WebExpress.WebUI.WebControl +//{ +// public class ControlTreeItemLink : ControlTreeItem +// { +// /// +// /// Returns or sets the target uri. +// /// +// public string Uri { get; set; } + +// /// +// /// Returns or sets the text. +// /// +// public string Text { get; set; } + +// /// +// /// Returns or sets the target. +// /// +// public TypeTarget Target { get; set; } + +// /// +// /// Returns or sets the tooltip. +// /// +// public string Title { get; set; } + +// /// +// /// Returns or sets a tooltip text. +// /// +// public string Tooltip { get; set; } + +// /// +// /// Returns or sets the icon. +// /// +// public PropertyIcon Icon { get; set; } + +// /// +// /// Liefert oder setzt die fΓΌr den Link gΓΌltigen Parameter +// /// +// public List Params { get; set; } + + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// public ControlTreeItemLink(string id = null) +// : base(id) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTreeItemLink(string id, params Control[] content) +// : base(id, content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlTreeItemLink(params Control[] content) +// : base(content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the control. +// /// The content of the html element. +// public ControlTreeItemLink(string id, List content) +// : base(id, content) +// { +// Init(); +// } + +// /// +// /// Initializes a new instance of the class. +// /// +// /// The content of the html element. +// public ControlTreeItemLink(List content) +// : base(content) +// { +// Init(); +// } + +// /// +// /// Initialization +// /// +// private void Init() +// { +// } + +// /// +// /// Returns all local and temporary parameters. +// /// +// /// The context in which the control is rendered. +// /// The parameters. +// public string GetParams(IPage page) +// { +// var dict = new Dictionary(); + +// // Übernahme der Parameter des Link +// if (Params != null) +// { +// foreach (var v in Params) +// { +// if (string.IsNullOrWhiteSpace(Uri?.ToString())) +// { +// if (!dict.ContainsKey(v.Key.ToLower())) +// { +// dict.Add(v.Key.ToLower(), v); +// } +// else +// { +// dict[v.Key.ToLower()] = v; +// } +// } +// } +// } + +// return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); +// } + +// /// +// /// Convert to html. +// /// +// /// The context in which the control is rendered. +// /// The control as html. +// public override IHtmlNode Render(IRenderContext context) +// { +// var param = ""; // GetParams(context?.Page); + +// var link = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) +// { +// Id = Id, +// Class = Css.Concatenate("link tree-link", Active == TypeActive.Active ? "tree-link-active" : ""), +// Role = Role, +// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), +// Target = Target, +// Title = Title, +// OnClick = OnClick?.ToString() +// }; + +// if (Icon != null && Icon.HasIcon) +// { +// link.Elements.Add(new ControlIcon() +// { +// Icon = Icon, +// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin +// ( +// PropertySpacing.Space.None, +// PropertySpacing.Space.Two, +// PropertySpacing.Space.None, +// PropertySpacing.Space.None +// ) : new PropertySpacingMargin(PropertySpacing.Space.None), +// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default +// }.Render(context)); +// } + +// if (!string.IsNullOrWhiteSpace(Text)) +// { +// link.Elements.Add(new HtmlText(Text)); +// } + +// if (!string.IsNullOrWhiteSpace(Tooltip)) +// { +// link.AddUserAttribute("data-toggle", "tooltip"); +// } + +// var expander = new HtmlElementTextSemanticsSpan +// { +// Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") +// }; + +// if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) +// { +// expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); +// } +// var container = new HtmlElementTextContentDiv(expander, link) +// { +// Class = Css.Concatenate("tree-treeview-container") +// }; + +// var html = new HtmlElementTextContentLi(Layout == TypeLayoutTreeItem.TreeView ? container : link) +// { +// Id = Id, +// Class = Css.Concatenate(Layout switch +// { +// TypeLayoutTreeItem.Group => "list-group-item-action", +// TypeLayoutTreeItem.Flush => "list-group-item-action", +// TypeLayoutTreeItem.Horizontal => "list-group-item-action", +// TypeLayoutTreeItem.TreeView => "tree-item", +// _ => "" +// }, Active.ToClass()), +// Style = GetStyles(), +// Role = Role +// }; + +// if (Children.Count > 0) +// { +// var items = (from x in Children select x.Render(context)).ToList(); +// var ul = new HtmlElementTextContentUl(items) +// { +// Class = Css.Concatenate(Layout switch +// { +// TypeLayoutTreeItem.TreeView => "tree-treeview-node", +// TypeLayoutTreeItem.Simple => "tree-simple-node", +// _ => Layout.ToClass() +// }, Expand.ToClass()) +// }; + +// switch (Layout) +// { +// case TypeLayoutTreeItem.Horizontal: +// case TypeLayoutTreeItem.Flush: +// case TypeLayoutTreeItem.Group: +// items.ForEach(x => x.AddClass("list-group-item")); +// break; +// } + +// html.Elements.Add(ul); +// } + +// return html; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/FormEventArgs.cs b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs index 493f8feb..710e2751 100644 --- a/src/WebExpress.WebUI/WebControl/FormEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs @@ -1,22 +1,22 @@ -ο»Ώusing System; +ο»Ώ//using System; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Event argument for forms. - /// - public class FormEventArgs : EventArgs - { - /// - /// The form context. - /// - public RenderContextForm Context { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Event argument for forms. +// /// +// public class FormEventArgs : EventArgs +// { +// /// +// /// The form context. +// /// +// public RenderContextForm Context { get; set; } - /// - /// Initializes a new instance of the class. - /// - public FormEventArgs() - { - } - } -} +// /// +// /// Initializes a new instance of the class. +// /// +// public FormEventArgs() +// { +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/IControl.cs b/src/WebExpress.WebUI/WebControl/IControl.cs index 805ddf95..e430fa90 100644 --- a/src/WebExpress.WebUI/WebControl/IControl.cs +++ b/src/WebExpress.WebUI/WebControl/IControl.cs @@ -1,8 +1,11 @@ ο»Ώusing WebExpress.WebCore.WebHtml; -using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { + /// + /// Interface for a control. + /// public interface IControl { /// @@ -11,10 +14,10 @@ public interface IControl string Id { get; } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - IHtmlNode Render(RenderContext context); + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + IHtmlNode Render(IRenderControlContext context); } } diff --git a/src/WebExpress.WebUI/WebControl/IControlForm.cs b/src/WebExpress.WebUI/WebControl/IControlForm.cs index 53a2e5ae..731b62bb 100644 --- a/src/WebExpress.WebUI/WebControl/IControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/IControlForm.cs @@ -1,90 +1,90 @@ -ο»Ώusing System; -using System.Collections.Generic; -using WebExpress.WebCore.WebMessage; +ο»Ώ//using System; +//using System.Collections.Generic; +//using WebExpress.WebCore.WebMessage; -namespace WebExpress.WebUI.WebControl -{ - public interface IControlForm : IControl - { - /// - /// Event to validate the input values. - /// - event EventHandler Validation; +//namespace WebExpress.WebUI.WebControl +//{ +// public interface IControlForm : IControl +// { +// /// +// /// Event to validate the input values. +// /// +// event EventHandler Validation; - /// - /// Event is raised when the form has been initialized. - /// - event EventHandler InitializeForm; +// /// +// /// Event is raised when the form has been initialized. +// /// +// event EventHandler InitializeForm; - /// - /// Event is raised when the form's data needs to be determined. - /// - event EventHandler FillForm; +// /// +// /// Event is raised when the form's data needs to be determined. +// /// +// event EventHandler FillForm; - /// - /// Event is raised when the form is about to be processed. - /// - event EventHandler ProcessForm; +// /// +// /// Event is raised when the form is about to be processed. +// /// +// event EventHandler ProcessForm; - /// - /// Event is raised when the form is to be processed and the next data is to be loaded. - /// - event EventHandler ProcessAndNextForm; +// /// +// /// Event is raised when the form is to be processed and the next data is to be loaded. +// /// +// event EventHandler ProcessAndNextForm; - /// - /// Returns or sets the name of the form. - /// - string Name { get; set; } +// /// +// /// Returns or sets the name of the form. +// /// +// string Name { get; set; } - /// - /// Returns or sets the target uri. - /// - string Uri { get; set; } +// /// +// /// Returns or sets the target uri. +// /// +// string Uri { get; set; } - /// - /// Returns or sets the redirect uri. - /// - string RedirectUri { get; set; } +// /// +// /// Returns or sets the redirect uri. +// /// +// string RedirectUri { get; set; } - /// - /// Returns or sets the form items. - /// - IEnumerable Items { get; } +// /// +// /// Returns or sets the form items. +// /// +// IEnumerable Items { get; } - /// - /// Returns or sets the request method. - /// - RequestMethod Method { get; set; } +// /// +// /// Returns or sets the request method. +// /// +// RequestMethod Method { get; set; } - /// - /// Initializes the form. - /// - /// The context in which the control is rendered. - void Initialize(RenderContextForm context); +// /// +// /// Initializes the form. +// /// +// /// The context in which the control is rendered. +// void Initialize(RenderContextForm context); - /// - /// Pre-processes the form. - /// - /// The context in which the control is rendered. - void PreProcess(RenderContextForm context); +// /// +// /// Pre-processes the form. +// /// +// /// The context in which the control is rendered. +// void PreProcess(RenderContextForm context); - /// - /// Adds form control items to the form. - /// - /// The form items. - void Add(params ControlFormItem[] item); +// /// +// /// Adds form control items to the form. +// /// +// /// The form items. +// void Add(params ControlFormItem[] item); - /// - /// Removes a form control item from the form. - /// - /// The form item. - void Remove(ControlFormItem formItem); +// /// +// /// Removes a form control item from the form. +// /// +// /// The form item. +// void Remove(ControlFormItem formItem); - /// - /// Validates the input elements for correctness of the data. - /// - /// The context in which the inputs are validated. - /// True if all form items are valid, false otherwise. - bool Validate(RenderContextForm context); - } -} +// /// +// /// Validates the input elements for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// /// True if all form items are valid, false otherwise. +// bool Validate(RenderContextForm context); +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/IFormValidation.cs b/src/WebExpress.WebUI/WebControl/IFormValidation.cs index 6366831c..6e9165b6 100644 --- a/src/WebExpress.WebUI/WebControl/IFormValidation.cs +++ b/src/WebExpress.WebUI/WebControl/IFormValidation.cs @@ -1,28 +1,28 @@ -ο»Ώusing System.Collections.Generic; +ο»Ώ//using System.Collections.Generic; -namespace WebExpress.WebUI.WebControl -{ - public interface IFormValidation - { - /// - /// Returns or sets whether the form element has been validated. - /// - //bool IsValidated { get; } +//namespace WebExpress.WebUI.WebControl +//{ +// public interface IFormValidation +// { +// /// +// /// Returns or sets whether the form element has been validated. +// /// +// //bool IsValidated { get; } - /// - /// Determines whether the inputs are valid. - /// - ICollection ValidationResults { get; } +// /// +// /// Determines whether the inputs are valid. +// /// +// ICollection ValidationResults { get; } - /// - /// Returns the most serious validation result. - /// - TypesInputValidity ValidationResult { get; } +// /// +// /// Returns the most serious validation result. +// /// +// TypesInputValidity ValidationResult { get; } - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - void Validate(RenderContextForm context); - } -} +// /// +// /// Checks the input element for correctness of the data. +// /// +// /// The context in which the inputs are validated. +// void Validate(RenderContextForm context); +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/PropertyModal.cs b/src/WebExpress.WebUI/WebControl/PropertyModal.cs index 9a062644..4b176d4e 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyModal.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyModal.cs @@ -1,37 +1,38 @@ ο»Ώnamespace WebExpress.WebUI.WebControl { + /// + /// Represents the characteristics of a modal. + /// public class PropertyModal { /// - /// Der Typ + /// The modal type. /// public TypeModal Type { get; protected set; } /// - /// Das benutzerdefinierte Modal + /// The custom modal. /// public ControlModal Modal { get; protected set; } /// - /// Die Grâße des Modals + /// The size of the modal. /// public TypeModalSize Size { get; protected set; } /// - /// Die Uri + /// The uri. /// public string Uri { get; protected set; } /// - /// Die Weiterleitungs-Uri + /// The forwarding uri. /// public string RedirectUri { get; set; } /// /// Initializes a new instance of the class. /// - /// Der Typ - /// Das benutzerdefinierte Modal oder null public PropertyModal() { Type = TypeModal.None; @@ -43,8 +44,8 @@ public PropertyModal() /// /// Initializes a new instance of the class. /// - /// Der Typ - /// Die Grâße des Modals + /// The modal type. + /// The size of the modal. public PropertyModal(TypeModal type, TypeModalSize size = TypeModalSize.Default) { Type = type; @@ -56,9 +57,9 @@ public PropertyModal(TypeModal type, TypeModalSize size = TypeModalSize.Default) /// /// Initializes a new instance of the class. /// - /// Der Typ - /// Das benutzerdefinierte Modal - /// Die Grâße des Modals + /// The modal type + /// Custom modal or null. + /// The size of the modal. public PropertyModal(TypeModal type, ControlModal modal, TypeModalSize size = TypeModalSize.Default) { Type = type; @@ -70,9 +71,9 @@ public PropertyModal(TypeModal type, ControlModal modal, TypeModalSize size = Ty /// /// Initializes a new instance of the class. /// - /// Der Typ - /// Die Uri - /// Die Grâße des Modals + /// The modal type + /// The uri. + /// The size of the modal. public PropertyModal(TypeModal type, string uri, TypeModalSize size = TypeModalSize.Default) { Type = type; diff --git a/src/WebExpress.WebUI/WebControl/RenderContextForm.cs b/src/WebExpress.WebUI/WebControl/RenderContextForm.cs index 51e1b6a0..dea117da 100644 --- a/src/WebExpress.WebUI/WebControl/RenderContextForm.cs +++ b/src/WebExpress.WebUI/WebControl/RenderContextForm.cs @@ -1,71 +1,71 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; +ο»Ώ//using System.Collections.Generic; +//using WebExpress.WebCore.WebMessage; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class RenderContextForm : RenderContext - { - /// - /// The form in which the control is rendered. - /// - public IControlForm Form { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class RenderContextForm : RenderContext +// { +// /// +// /// The form in which the control is rendered. +// /// +// public IControlForm Form { get; private set; } - /// - /// Returns or sets the links to the java script files to be used. - /// - public IDictionary Scripts { get; } = new Dictionary(); +// /// +// /// Returns or sets the links to the java script files to be used. +// /// +// public IDictionary Scripts { get; } = new Dictionary(); - /// - /// Returns the validation errors. - /// - public ICollection ValidationResults { get; } = new List(); +// /// +// /// Returns the validation errors. +// /// +// public ICollection ValidationResults { get; } = new List(); - /// - /// Initializes a new instance of the class. - /// - /// The page where the control is rendered. - /// The request. - /// The visual tree. - /// The form in which the control is rendered. - public RenderContextForm(IPage page, Request request, IVisualTree visualTree, IControlForm form) - : base(page, request, visualTree) - { - Form = form; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The page where the control is rendered. +// /// The request. +// /// The visual tree. +// /// The form in which the control is rendered. +// public RenderContextForm(IPage page, Request request, IVisualTree visualTree, IControlForm form) +// //: base(page, request, visualTree) +// { +// Form = form; +// } - /// - /// Initializes a new instance of the class. - /// - /// The context in which the control is rendered. - /// The form in which the control is rendered. - public RenderContextForm(RenderContext context, IControlForm form) - : base(context) - { - Form = form; - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The context in which the control is rendered. +// /// The form in which the control is rendered. +// public RenderContextForm(RenderContext context, IControlForm form) +// : base(context) +// { +// Form = form; +// } - /// - /// Copy-Constructor - /// - /// The render context to copy./param> - public RenderContextForm(RenderContextForm context) - : this(context, context?.Form) - { - Scripts = context.Scripts; - } +// /// +// /// Copy-Constructor +// /// +// /// The render context to copy./param> +// public RenderContextForm(RenderContextForm context) +// : this(context, context?.Form) +// { +// Scripts = context.Scripts; +// } - /// - /// Adds or replaces a java script if it exists. - /// - /// The key. - /// The java script code. - public void AddScript(string key, string code) - { - if (!Scripts.ContainsKey(key)) - { - Scripts.Add(key, code); - } - } - } -} +// /// +// /// Adds or replaces a java script if it exists. +// /// +// /// The key. +// /// The java script code. +// public void AddScript(string key, string code) +// { +// if (!Scripts.ContainsKey(key)) +// { +// Scripts.Add(key, code); +// } +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs b/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs index 393925f5..67d5312f 100644 --- a/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs +++ b/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs @@ -1,34 +1,34 @@ -ο»Ώusing WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebControl -{ - public class RenderContextFormGroup : RenderContextForm - { - /// - /// Die Gruppe, indem das Steuerelement gerendert wird - /// - public ControlFormItemGroup Group { get; private set; } +//namespace WebExpress.WebUI.WebControl +//{ +// public class RenderContextFormGroup : RenderContextForm +// { +// /// +// /// Die Gruppe, indem das Steuerelement gerendert wird +// /// +// public ControlFormItemGroup Group { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The context in which the control is rendered. - /// The form in which the control is rendered. - /// Die Gruppe - public RenderContextFormGroup(RenderContext context, ControlForm form, ControlFormItemGroup group) - : base(context, form) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The context in which the control is rendered. +// /// The form in which the control is rendered. +// /// Die Gruppe +// public RenderContextFormGroup(RenderContext context, ControlForm form, ControlFormItemGroup group) +// : base(context, form) +// { +// } - /// - /// Initializes a new instance of the class. - /// - /// The context in which the control is rendered. - /// Die Gruppe - public RenderContextFormGroup(RenderContextForm context, ControlFormItemGroup group) - : base(context) - { - Group = group; - } - } -} +// /// +// /// Initializes a new instance of the class. +// /// +// /// The context in which the control is rendered. +// /// Die Gruppe +// public RenderContextFormGroup(RenderContextForm context, ControlFormItemGroup group) +// : base(context) +// { +// Group = group; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebControl/TypeColorButton.cs b/src/WebExpress.WebUI/WebControl/TypeColorButton.cs index d141eca5..56157c4a 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorButton.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorButton.cs @@ -1,5 +1,8 @@ ο»Ώnamespace WebExpress.WebUI.WebControl { + /// + /// Enumeration of button color types. + /// public enum TypeColorButton { Default = 0, @@ -13,6 +16,9 @@ public enum TypeColorButton Light = 8 } + /// + /// Provides extension methods for the TypeColorButton enumeration. + /// public static class TypeColorButtonExtensions { /// diff --git a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs index 0261d058..54d139fa 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs @@ -1,27 +1,27 @@ -ο»Ώusing System.Collections.Generic; +ο»Ώ//using System.Collections.Generic; -namespace WebExpress.WebUI.WebControl -{ - /// - /// Event argument for validating form inputs. - /// - public class ValidationEventArgs : FormEventArgs - { - /// - /// Returns or sets the value to be checked. - /// - public string Value { get; set; } +//namespace WebExpress.WebUI.WebControl +//{ +// /// +// /// Event argument for validating form inputs. +// /// +// public class ValidationEventArgs : FormEventArgs +// { +// /// +// /// Returns or sets the value to be checked. +// /// +// public string Value { get; set; } - /// - /// Returns or sets the validation results. - /// - public List Results { get; } = new List(); +// /// +// /// Returns or sets the validation results. +// /// +// public List Results { get; } = new List(); - /// - /// Initializes a new instance of the class. - /// - public ValidationEventArgs() - { - } - } -} +// /// +// /// Initializes a new instance of the class. +// /// +// public ValidationEventArgs() +// { +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebExUI.cs b/src/WebExpress.WebUI/WebExUI.cs new file mode 100644 index 00000000..531a1255 --- /dev/null +++ b/src/WebExpress.WebUI/WebExUI.cs @@ -0,0 +1,25 @@ +ο»Ώusing System.Runtime.CompilerServices; +using WebExpress.WebCore; +using WebExpress.WebCore.WebComponent; +using WebExpress.WebUI.WebComponent; + +[assembly: InternalsVisibleTo("WebExpress.WebUI.Test")] + +namespace WebExpress.WebUI +{ + /// + /// Represents the WebExpress UI component that extends the WebEx class with the IComponentHubUI interface. + /// + public class WebExUI : WebEx + { + /// + /// Creates and returns a new instance of . + /// + /// The HTTP server context used to initialize the component manager. + /// A new instance of . + protected override IComponentHubUI CreateComponentManager(IHttpServerContext httpServerContext) + { + return ComponentActivator.CreateInstance(httpServerContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index a3e3d34a..194d7020 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -5,7 +5,7 @@ WebExpress.WebUI 0.0.8.0 0.0.8.0 - net8.0 + net9.0 any https://github.com/ReneSchwarzer/WebExpress.WebUI Rene_Schwarzer@hotmail.de @@ -396,6 +396,7 @@ + diff --git a/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs b/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs deleted file mode 100644 index 05ce7772..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentCacheItem.cs +++ /dev/null @@ -1,86 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentCacheItem - { - /// - /// Returns the type. - /// - private Type Type { get; set; } - - /// - /// Returns or sets the fragment instance. - /// - private IFragment Instance { get; set; } - - /// - /// Provides the context of the fragment. - /// - public IFragmentContext Context { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The context of the fragment. - /// The type. - public FragmentCacheItem(IFragmentContext context, Type type) - { - Context = context; - Type = type; - } - - /// - /// Creates a new instance or returns a cached instance. - /// - /// The page in which the fragment is active. - /// The request. - /// An enumeration of the fragment instances. - public IEnumerable CreateInstance(IPage page, Request request = null) where T : IControl - { - if (request != null && !CheckControl(request)) - { - return new List(); - } - else if (Context.Cache && Instance != null) - { - return new List() { (T)Instance }; - } - - if (Activator.CreateInstance(Type) is IFragment instance) - { - instance.Initialization(Context, page); - - if (Context.Cache) - { - Instance = instance; - } - - return new List() { (T)instance }; - } - else if (Activator.CreateInstance(Type) is IFragmentDynamic dynamicInstance) - { - dynamicInstance.Initialization(Context, page); - - return dynamicInstance.Create(); - } - - return new List(); - } - - /// - /// Checks the component to see if they are displayed or disabled. - /// - /// The request. - /// True the fragment is active, false otherwise. - private bool CheckControl(Request request) - { - return !Context.Conditions.Any() || Context.Conditions.All(x => x.Fulfillment(request)); - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentComparer.cs b/src/WebExpress.WebUI/WebFragment/FragmentComparer.cs deleted file mode 100644 index 7688f1c8..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentComparer.cs +++ /dev/null @@ -1,40 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace WebExpress.WebUI.WebFragment -{ - [Obsolete] - public class FragmentComparer : IEqualityComparer - { - /// - /// Tests for equality. - /// - /// The first object to compare. - /// The second object to compare. - /// True if both objects are similar; false otherwise. - public bool Equals(T x, T y) - { - if (x == null && y == null) - { - return true; - } - else if (x.GetType() == y.GetType()) - { - return true; - } - - return false; - } - - /// - /// Returns a hash code for the specified object. - /// - /// The object for which to return a hash code. - /// The hash code. - public int GetHashCode([DisallowNull] T obj) - { - return obj.GetType().GetHashCode(); - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs b/src/WebExpress.WebUI/WebFragment/FragmentContext.cs deleted file mode 100644 index 566ed0b8..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentContext.cs +++ /dev/null @@ -1,52 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using System.Globalization; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Represents the context for a web fragment, including plugin context, application context, - /// conditions for activation, culture information, and caching behavior. - /// - public class FragmentContext : IFragmentContext - { - /// - /// Returns the context of the associated plugin. - /// - public IPluginContext PluginContext { get; internal set; } - - /// - /// Returns the application context. - /// - public IApplicationContext ApplicationContext { get; internal set; } - - /// - /// Gets the unique identifier for the fragment. - /// - public string FragmentId { get; internal set; } - - /// - /// Returns the conditions that must be met for the component to be active. - /// - public ICollection Conditions { get; internal set; } = []; - - /// - /// Returns the culture. - /// - public CultureInfo Culture { get; set; } - - /// - /// Determines whether the component is created once and reused on each execution. - /// - public bool Cache { get; internal set; } - - /// - /// Initializes a new instance of the class. - /// - public FragmentContext() - { - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs index 5d46751c..036feddc 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs @@ -1,32 +1,35 @@ -ο»Ώusing WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebFragment { - public class FragmentControlButtonLink : ControlButtonLink, IFragment + /// + /// Represents a button link control fragment that can be processed and rendered within a web page. + /// + public abstract class FragmentControlButtonLink : ControlButtonLink, IFragmentControl { /// - /// Returns the context of the fragment. + /// Gets the context of the fragment. /// - public IFragmentContext FragmentContext { get; private set; } + public IFragmentContext FragmentContext { get; } /// /// Initializes a new instance of the class. /// - /// The id of the fragment or null. - public FragmentControlButtonLink(string id = null) - : base(id) + /// The context of the fragment. + protected FragmentControlButtonLink(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) { + FragmentContext = fragmentContext; } /// - /// Initialization + /// Releases all resources used by the fragment. /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) + public virtual void Dispose() { - FragmentContext = context; + GC.SuppressFinalize(this); } } -} +} \ No newline at end of file diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs index bcdd87b6..b8b706dc 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragment - { - /// - /// Liefert der Kontext - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragment +// { +// /// +// /// Liefert der Kontext +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlDropdownItemLink(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlDropdownItemLink(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs index 121c4b76..47b9f499 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs @@ -1,32 +1,36 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebFragment { - public class FragmentControlImage : ControlImage, IFragment + /// + /// Represents a image control fragment that can be processed and rendered within a web page. + /// + public abstract class FragmentControlImage : ControlImage, IFragmentControl { /// - /// Returns the context of the fragment. + /// Gets the context of the fragment. /// - public IFragmentContext FragmentContext { get; private set; } + public IFragmentContext FragmentContext { get; } /// /// Initializes a new instance of the class. /// - /// The id of the fragment or null. - public FragmentControlImage(string id = null) - : base(id) + /// The context of the fragment. + protected FragmentControlImage(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) { + FragmentContext = fragmentContext; } /// - /// Initialization + /// Releases all resources used by the fragment. /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) + public virtual void Dispose() { - FragmentContext = context; + GC.SuppressFinalize(this); } } } + diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs index 2d668cb0..ead4e4d3 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs @@ -1,32 +1,35 @@ -ο»Ώusing WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebFragment { - public class FragmentControlLink : ControlLink, IFragment + /// + /// Represents a link control fragment that can be processed and rendered within a web page. + /// + public abstract class FragmentControlLink : ControlLink, IFragmentControl { /// - /// Returns the context of the fragment. + /// Gets the context of the fragment. /// - public IFragmentContext FragmentContext { get; private set; } + public IFragmentContext FragmentContext { get; } /// /// Initializes a new instance of the class. /// - /// The id of the fragment or null. - public FragmentControlLink(string id = null) - : base(id) + /// The context of the fragment. + protected FragmentControlLink(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) { + FragmentContext = fragmentContext; } /// - /// Initialization + /// Releases all resources used by the fragment. /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) + public virtual void Dispose() { - FragmentContext = context; + GC.SuppressFinalize(this); } } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs index df99e3cc..a88e3b51 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs @@ -1,32 +1,35 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebFragment { - public class FragmentControlList : ControlList, IFragment + /// + /// Represents a list control fragment that can be processed and rendered within a web page. + /// + public abstract class FragmentControlList : ControlList, IFragmentControl { /// - /// Returns the context of the fragment. + /// Gets the context of the fragment. /// - public IFragmentContext FragmentContext { get; private set; } + public IFragmentContext FragmentContext { get; } /// /// Initializes a new instance of the class. /// - /// The id of the fragment or null. - public FragmentControlList(string id = null) - : base(id) + /// The context of the fragment. + protected FragmentControlList(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) { + FragmentContext = fragmentContext; } /// - /// Initialization + /// Releases all resources used by the fragment. /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) + public virtual void Dispose() { - FragmentContext = context; + GC.SuppressFinalize(this); } } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs index 73e97aaa..d8bd6b6c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebCore.WebPage; -using WebExpress.WebUI.WebControl; +ο»Ώ//using WebExpress.WebCore.WebPage; +//using WebExpress.WebUI.WebControl; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlModalForm : ControlModalForm, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlModalForm : ControlModalForm, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlModalForm(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlModalForm(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs index b46d5eb9..f36db8c7 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlNavigationItemLink : ControlNavigationItemLink, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlNavigationItemLink : ControlNavigationItemLink, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlNavigationItemLink(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlNavigationItemLink(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs index 0cd39371..9d29a954 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlPanel : ControlPanel, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlPanel : ControlPanel, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlPanel(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlPanel(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs index 29e0da5f..69c2589f 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlPanelFlexbox : ControlPanelFlexbox, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlPanelFlexbox : ControlPanelFlexbox, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlPanelFlexbox(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlPanelFlexbox(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs index 03b7178c..f12e3068 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlPanelTool : ControlPanelTool, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlPanelTool : ControlPanelTool, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlPanelTool(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlPanelTool(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs index 818b16d1..6ca1f47f 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlSplitButtonItemLink : ControlSplitButtonItemLink, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlSplitButtonItemLink : ControlSplitButtonItemLink, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlSplitButtonItemLink(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlSplitButtonItemLink(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs index 1364ef7c..3002c2fb 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs @@ -1,32 +1,35 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebFragment { - public class FragmentControlText : ControlText, IFragment + /// + /// Represents a text control fragment that can be processed and rendered within a web page. + /// + public abstract class FragmentControlText : ControlText, IFragmentControl { /// - /// Returns the context of the fragment. + /// Gets the context of the fragment. /// - public IFragmentContext FragmentContext { get; private set; } + public IFragmentContext FragmentContext { get; } /// /// Initializes a new instance of the class. /// - /// The id of the fragment or null. - public FragmentControlText(string id = null) - : base(id) + /// The context of the fragment. + protected FragmentControlText(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) { + FragmentContext = fragmentContext; } /// - /// Initialization + /// Releases all resources used by the fragment. /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) + public virtual void Dispose() { - FragmentContext = context; + GC.SuppressFinalize(this); } } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs index bc297cce..e0111539 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs @@ -1,32 +1,32 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; +ο»Ώ//using WebExpress.WebUI.WebControl; +//using WebExpress.WebCore.WebPage; -namespace WebExpress.WebUI.WebFragment -{ - public class FragmentControlTree : ControlTree, IFragment - { - /// - /// Returns the context of the fragment. - /// - public IFragmentContext FragmentContext { get; private set; } +//namespace WebExpress.WebUI.WebFragment +//{ +// public class FragmentControlTree : ControlTree, IFragment +// { +// /// +// /// Returns the context of the fragment. +// /// +// public IFragmentContext FragmentContext { get; private set; } - /// - /// Initializes a new instance of the class. - /// - /// The id of the fragment or null. - public FragmentControlTree(string id = null) - : base(id) - { - } +// /// +// /// Initializes a new instance of the class. +// /// +// /// The id of the fragment or null. +// public FragmentControlTree(string id = null) +// : base(id) +// { +// } - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - public virtual void Initialization(IFragmentContext context, IPage page) - { - FragmentContext = context; - } - } -} +// /// +// /// Initialization +// /// +// /// The context. +// /// The page where the fragment is active. +// public virtual void Initialization(IFragmentContext context, IPage page) +// { +// FragmentContext = context; +// } +// } +//} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs b/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs deleted file mode 100644 index 1d7d2180..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentItemComparer.cs +++ /dev/null @@ -1,31 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebUI.WebFragment.Model; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Test of two fragments for equality. - /// - internal class FragmentItemComparer : IComparer - { - /// - /// Compares two objects and returns a value indicating whether one value is lower, equal, or greater than the other value. - /// - /// The first object to compare. - /// The second object to compare. - /// A signed integer that specifies the relative values of x and y. Less than 0 => x is less than y. Greater than 0 => x is greater than y. 0 (zero) => x is equal to y. - public int Compare(FragmentItem x, FragmentItem y) - { - if (x.Order > y.Order) - { - return 1; - } - else if (x.Order < y.Order) - { - return -1; - } - - return 0; - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs b/src/WebExpress.WebUI/WebFragment/FragmentManager.cs deleted file mode 100644 index 055b4c69..00000000 --- a/src/WebExpress.WebUI/WebFragment/FragmentManager.cs +++ /dev/null @@ -1,464 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebAttribute; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebPlugin; -using WebExpress.WebUI.WebAttribute; -using WebExpress.WebUI.WebControl; -using WebExpress.WebUI.WebFragment.Model; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Fragment manager. - /// - public sealed class FragmentManager : IFragmentManager - { - private readonly IComponentHub _componentHub; - private readonly IHttpServerContext _httpServerContext; - private readonly FragmentDictionary _dictionary = []; - - /// - /// An event that fires when an fragment is added. - /// - public event EventHandler AddFragment; - - /// - /// An event that fires when an fragment is removed. - /// - public event EventHandler RemoveFragment; - - /// - /// Initializes a new instance of the class. - /// - /// The component hub. - /// The reference to the context of the host. - private FragmentManager(IComponentHub componentHub, IHttpServerContext httpServerContext) - { - _componentHub = componentHub; - _httpServerContext = httpServerContext; - - _componentHub.PluginManager.AddPlugin += OnAddPlugin; - _componentHub.PluginManager.RemovePlugin += OnRemovePlugin; - _componentHub.ApplicationManager.AddApplication += OnAddApplication; - _componentHub.ApplicationManager.RemoveApplication += OnRemoveApplication; - - _httpServerContext.Log.Debug - ( - I18N.Translate("webexpress.webui:fragmentmanager.initialization") - ); - } - - /// - /// Discovers and binds fragments to an application. - /// - /// The context of the plugin whose fragments are to be associated. - private void Register(IPluginContext pluginContext) - { - if (_dictionary.ContainsKey(pluginContext)) - { - return; - } - - Register(pluginContext, _componentHub.ApplicationManager.GetApplications(pluginContext)); - } - - /// - /// Discovers and binds fragments to an application. - /// - /// The context of the application whose fragments are to be associated. - private void Register(IApplicationContext applicationContext) - { - foreach (var pluginContext in _componentHub.PluginManager.GetPlugins(applicationContext)) - { - if (_dictionary.TryGetValue(pluginContext, out var appDict) && appDict.ContainsKey(applicationContext)) - { - continue; - } - - Register(pluginContext, [applicationContext]); - } - } - - /// - /// Registers pages for a given plugin and application context. - /// - /// The plugin context. - /// The application context (optional). - private void Register(IPluginContext pluginContext, IEnumerable applicationContexts) - { - var assembly = pluginContext.Assembly; - - foreach (var fragmentType in assembly.GetTypes().Where - ( - x => x.IsClass && - x.IsSealed && - x.IsPublic && - ( - x.GetInterfaces().Contains(typeof(IFragment)) || - x.GetInterfaces().Contains(typeof(IFragmentDynamic)) - ) - )) - { - var id = fragmentType.FullName?.ToLower(); - var scopes = new List(); - var section = string.Empty; - var conditions = new List(); - var cache = false; - var order = 0; - - // determining attributes - foreach (var customAttribute in fragmentType.CustomAttributes.Where - ( - x => x.AttributeType.GetInterfaces() - .Contains(typeof(IEndpointAttribute)) - )) - { - if (customAttribute.AttributeType.Name == typeof(ScopeAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ScopeAttribute<>).Namespace) - { - scopes.Add(customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower()); - } - else if (customAttribute.AttributeType.Name == typeof(ConditionAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ConditionAttribute<>).Namespace) - { - var condition = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault(); - conditions.Add(Activator.CreateInstance(condition) as ICondition); - } - else if (customAttribute.AttributeType == typeof(CacheAttribute)) - { - cache = true; - } - } - - foreach (var customAttribute in fragmentType.CustomAttributes.Where - ( - x => x.AttributeType.GetInterfaces().Contains(typeof(IFragmentAttribute)) - )) - { - if (customAttribute.AttributeType == typeof(SectionAttribute)) - { - section = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString().ToLower(); - } - else if (customAttribute.AttributeType == typeof(OrderAttribute)) - { - try - { - order = Convert.ToInt32(customAttribute.ConstructorArguments.FirstOrDefault().Value); - } - catch - { - } - } - } - - // check section - if (string.IsNullOrWhiteSpace(section)) - { - _httpServerContext.Log.Warning(I18N.Translate - ( - "webexpress.webui:fragmentmanager.error.section" - )); - - continue; - } - - // assign the fragment to existing applications - foreach (var applicationContext in _componentHub.ApplicationManager.GetApplications(pluginContext)) - { - // register fragment - foreach (var context in scopes.Count != 0 ? scopes : [""]) - { - var fragmentContext = new FragmentContext() - { - PluginContext = pluginContext, - ApplicationContext = applicationContext, - FragmentId = id, - Cache = cache, - //Scopes = scopes, - Conditions = conditions - }; - - var fragmentItem = new FragmentItem() - { - PluginContext = pluginContext, - ApplicationContext = applicationContext, - FragmentContext = fragmentContext, - FragmentClass = fragmentType, - Order = order, - Cache = cache, - Conditions = conditions, - Section = section, - Scopes = scopes - }; - - if (_dictionary.AddFragmentItem(pluginContext, applicationContext, fragmentItem)) - { - OnAddFragment(fragmentContext); - - _httpServerContext?.Log.Debug - ( - I18N.Translate - ( - "webexpress:fragmentmanager.register", - id, - section, - applicationContext.ApplicationId - ) - ); - } - } - } - } - - Log(); - } - - /// - /// Removes all components associated with the specified plugin context. - /// - /// The context of the plugin that contains the components to remove. - internal void Remove(IPluginContext pluginContext) - { - if (pluginContext == null) - { - return; - } - - var fragments = _dictionary.RemoveFragments(pluginContext); - - foreach (var fragment in fragments) - { - OnRemoveFragment(fragment); - } - } - - /// - /// Removes all fragments associated with the specified application context. - /// - /// The context of the application that contains the fragments to remove. - internal void Remove(IApplicationContext applicationContext) - { - if (applicationContext == null) - { - return; - } - - var fragments = _dictionary.RemoveFragments(applicationContext); - - foreach (var fragment in fragments) - { - OnRemoveFragment(fragment); - } - } - - /// - /// Raises the AddFragment event. - /// - /// The fragment context. - private void OnAddFragment(IFragmentContext fragmentContext) - { - AddFragment?.Invoke(this, fragmentContext); - } - - /// - /// Raises the RemoveFragment event. - /// - /// The fragment context. - private void OnRemoveFragment(IFragmentContext fragmentContext) - { - RemoveFragment?.Invoke(this, fragmentContext); - } - - /// - /// Raises the event when an plugin is added. - /// - /// The source of the event. - /// The context of the plugin being added. - private void OnAddPlugin(object sender, IPluginContext e) - { - Register(e); - } - - /// - /// Raises the event when a plugin is removed. - /// - /// The source of the event. - /// The context of the plugin being removed. - private void OnRemovePlugin(object sender, IPluginContext e) - { - Remove(e); - } - - /// - /// Raises the event when an application is added. - /// - /// The source of the event. - /// The context of the application being added. - private void OnAddApplication(object sender, IApplicationContext e) - { - Register(e); - } - - /// - /// Raises the event when an application is removed. - /// - /// The source of the event. - /// The context of the application being removed. - private void OnRemoveApplication(object sender, IApplicationContext e) - { - Remove(e); - } - - /// - /// Returns all fragment contexts that belong to a given section. - /// - /// The section where the fragment is embedded. - /// An enumeration of the filtered fragment contexts. - public IEnumerable GetFragmentContexts(string section) - { - return GetFragmentItems(section) - .SelectMany(x => x.FragmentContexts); - } - - /// - /// Returns all fragment contexts that belong to a given application. - /// - /// The section where the fragment is embedded. - /// The allpication context. - /// An enumeration of the filtered fragment contexts. - public IEnumerable GetFragmentContexts(string section, IApplicationContext applicationContext) - { - return GetFragmentItems(section) - .SelectMany(x => x.FragmentContexts) - .Where(x => x.ApplicationContext == applicationContext); - } - - /// - /// Returns all fragment contexts that belong to a given application. - /// - /// The section where the fragment is embedded. - /// An enumeration of the filtered fragment contexts. - private IEnumerable GetFragmentItems(string section) - { - return _dictionary.Values - .Where(x => x.ContainsKey(section?.ToLower())) - .SelectMany(x => x[section?.ToLower()]) - .Select(x => x); - } - - /// - /// Determines all fragments that match the parameters. - /// - /// The section where the fragment is embedded. - /// The page that holds the fragments. - /// A list of fragments. - public IEnumerable GetCacheableFragments - ( - string section, - IPage page - ) where T : IControl - { - return GetCacheableFragments(section, page, page?.ResourceContext?.Scopes); - } - - /// - /// Determines all fragments that match the parameters. - /// - /// The section where the fragment is embedded. - /// The page that holds the fragments. - /// The scopes where the fragments exists. - /// A list of fragments. - public IEnumerable GetCacheableFragments - ( - string section, - IPage page, - IEnumerable scopes - ) where T : IControl - { - var applicationContext = page?.ResourceContext?.ModuleContext?.ApplicationContext; - scopes ??= Enumerable.Empty(); - - var fragmentItems = GetFragmentItems($"{section}:") - .Union(scopes.SelectMany(x => GetFragmentItems - ( - string.Join(":", section?.ToLower(), x?.ToLower()) - ))); - - var fragmentCacheItems = fragmentItems.Where - ( - x => x.FragmentClass.GetInterfaces().Contains(typeof(T)) || - x.FragmentClass.GetInterfaces().Contains(typeof(IFragmentDynamic)) - ) - .Select(x => new - { - x.FragmentClass, - FragmentContext = x.FragmentContexts - .Where(y => y.ModuleContext?.ApplicationContext == applicationContext) - .FirstOrDefault() - }) - .Where(x => x.FragmentContext != null) - .Select(x => new FragmentCacheItem(x.FragmentContext, x.FragmentClass)); - - return fragmentCacheItems; - } - - /// - /// Returns the fragment items. - /// - /// The context of the plugin. - /// A list with the fragment items. - private IEnumerable GetFragmentItems(IPluginContext pluginContext) - { - if (!_dictionary.ContainsKey(pluginContext)) - { - return []; - } - - return _dictionary[pluginContext].Values - .SelectMany(x => x); - } - - /// - /// Information about the component is collected and prepared for output in the log. - /// - private void Log() - { - //output.Add - //( - // string.Empty.PadRight(deep) + - // I18N.Translate("webexpress.webui:fragmentmanager.titel") - //); - - //foreach (var fragmentItem in GetFragmentItems(pluginContext)) - //{ - // output.Add - // ( - // string.Empty.PadRight(deep + 2) + - // I18N.Translate - // ( - // "webexpress.webui:fragmentmanager.fragment", - // fragmentItem.FragmentClass.Name - // ) - // ); - //} - } - - /// - /// Release of unmanaged resources reserved during use. - /// - public void Dispose() - { - _componentHub.PluginManager.AddPlugin -= OnAddPlugin; - _componentHub.PluginManager.RemovePlugin -= OnRemovePlugin; - _componentHub.ApplicationManager.AddApplication -= OnAddApplication; - _componentHub.ApplicationManager.RemoveApplication -= OnRemoveApplication; - - GC.SuppressFinalize(this); - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/IFragment.cs b/src/WebExpress.WebUI/WebFragment/IFragment.cs deleted file mode 100644 index 20ad3a55..00000000 --- a/src/WebExpress.WebUI/WebFragment/IFragment.cs +++ /dev/null @@ -1,20 +0,0 @@ -ο»Ώusing WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebFragment -{ - public interface IFragment : IControl - { - /// - /// Returns the context of the fragment. - /// - IFragmentContext FragmentContext { get; } - - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - void Initialization(IFragmentContext context, IPage page); - } -} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs b/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs deleted file mode 100644 index 24b919dc..00000000 --- a/src/WebExpress.WebUI/WebFragment/IFragmentContext.cs +++ /dev/null @@ -1,40 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Interface representing the context of a web fragment. - /// Provides access to plugin context, application context, conditions for activation, and caching behavior. - /// - public interface IFragmentContext : IContext - { - /// - /// Returns the context of the associated plugin. - /// - IPluginContext PluginContext { get; } - - /// - /// Returns the application context. - /// - IApplicationContext ApplicationContext { get; } - - /// - /// Gets the unique identifier for the fragment. - /// - string FragmentId { get; } - - /// - /// Returns the conditions that must be met for the component to be active. - /// - ICollection Conditions { get; } - - /// - /// Determines whether the component is created once and reused on each execution. - /// - bool Cache { get; } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs new file mode 100644 index 00000000..3fa39b57 --- /dev/null +++ b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs @@ -0,0 +1,18 @@ +ο»Ώusing WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a fragment interface with a generic type parameter. + /// + /// The type of control that implements the IControl interface. + public interface IFragmentControl : IFragment where T : class, IControl + { + /// + /// Gets the context of the fragment. + /// + IFragmentContext FragmentContext { get; } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentDynamic.cs b/src/WebExpress.WebUI/WebFragment/IFragmentDynamic.cs deleted file mode 100644 index 6bfa701a..00000000 --- a/src/WebExpress.WebUI/WebFragment/IFragmentDynamic.cs +++ /dev/null @@ -1,27 +0,0 @@ -ο»Ώusing System.Collections.Generic; -using WebExpress.WebUI.WebControl; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebFragment -{ - public interface IFragmentDynamic - { - /// - /// Returns the context of the fragment.. - /// - IFragmentContext Context { get; } - - /// - /// Initialization - /// - /// The context. - /// The page where the fragment is active. - void Initialization(IFragmentContext context, IPage page); - - /// - /// Creates fragments of a common type T. - /// - /// The created instances of the fragments. - IEnumerable Create() where T : IControl; - } -} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs b/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs deleted file mode 100644 index 49bb76fc..00000000 --- a/src/WebExpress.WebUI/WebFragment/IFragmentManager.cs +++ /dev/null @@ -1,57 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebCore.WebPage; -using WebExpress.WebUI.WebControl; - -namespace WebExpress.WebUI.WebFragment -{ - /// - /// Interface for managing web fragments. - /// - public interface IFragmentManager : IComponentManager - { - /// - /// An event that fires when a fragment is added. - /// - public event EventHandler AddFragment; - - /// - /// An event that fires when a fragment is removed. - /// - public event EventHandler RemoveFragment; - - /// - /// Returns all fragment contexts that belong to a given section. - /// - /// The section where the fragment is embedded. - /// An enumeration of the filtered fragment contexts. - IEnumerable GetFragmentContexts(string section); - - /// - /// Returns all fragment contexts that belong to a given application. - /// - /// The section where the fragment is embedded. - /// The allpication context. - /// An enumeration of the filtered fragment contexts. - IEnumerable GetFragmentContexts(string section, IApplicationContext applicationContext); - - /// - /// Determines all fragments that match the parameters. - /// - /// The section where the fragment is embedded. - /// The page that holds the fragments. - /// A list of fragments. - IEnumerable GetCacheableFragments(string section, IPage page) where T : IControl; - - /// - /// Determines all fragments that match the parameters. - /// - /// The section where the fragment is embedded. - /// The page that holds the fragments. - /// The scopes where the fragments exists. - /// A list of fragments. - IEnumerable GetCacheableFragments(string section, IPage page, IEnumerable scopes) where T : IControl; - } -} diff --git a/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs b/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs deleted file mode 100644 index 90b9ac4f..00000000 --- a/src/WebExpress.WebUI/WebFragment/Model/FragmentDictionary.cs +++ /dev/null @@ -1,151 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment.Model -{ - /// - /// Represents a dictionary that maps plugin contexts to application contexts, - /// which in turn maps to a dictionary of string keys and lists of FragmentItem objects. - /// key = plugin context - /// value application context { key = section:context, value = component item } - /// - internal class FragmentDictionary : Dictionary>>> - { - /// - /// Adds a fragment item to the dictionary. - /// - /// The plugin context. - /// The application context. - /// The fragment item. - /// True if the fragment item was added successfully, false if an element with the same status code already exists. - public bool AddFragmentItem(IPluginContext pluginContext, IApplicationContext applicationContext, FragmentItem fragmentItem) - { - var type = fragmentItem.FragmentClass; - - if (!typeof(IFragment).IsAssignableFrom(type)) - { - return false; - } - - if (!ContainsKey(pluginContext)) - { - this[pluginContext] = []; - } - - var appContextDict = this[pluginContext]; - - if (!appContextDict.ContainsKey(applicationContext)) - { - appContextDict[applicationContext] = []; - } - - var fragmentDict = appContextDict[applicationContext]; - - if (!fragmentDict.ContainsKey(type)) - { - fragmentDict[type] = []; - return true; - } - - return false; // item with the same fragment class already exists - } - - /// - /// Removes fragments from the dictionary. - /// - /// The plugin context. - /// An IEnumerable of fragment contexts that were removed. - public IEnumerable RemoveFragments(IPluginContext pluginContext) - { - var fragments = GetFragments(pluginContext); - - Remove(pluginContext); - - return fragments; - } - - /// - /// Removes fragments from the dictionary. - /// - /// The application context. - /// An IEnumerable of fragment contexts that were removed. - public IEnumerable RemoveFragments(IApplicationContext applicationContext) - { - foreach (var appContextDict in this) - { - if (appContextDict.Value.TryGetValue(applicationContext, out var fragmentDict)) - { - appContextDict.Value.Remove(applicationContext); - - if (appContextDict.Value.Count == 0) - { - Remove(appContextDict.Key); - } - - return fragmentDict.Values.SelectMany(x => x).Select(x => x.FragmentContext); - } - } - - return []; - } - - /// - /// Returns the fragment items from the dictionary. - /// - /// The type of fragment. - /// The application context. - /// An IEnumerable of fragment items - public IEnumerable GetFragmentItems(IApplicationContext applicationContext) where T : IFragment - { - return GetFragmentItems(applicationContext, typeof(T)); - } - - /// - /// Returns the fragment items from the dictionary. - /// - /// The application context. - /// The type of fragment. - /// An IEnumerable of fragment items - public IEnumerable GetFragmentItems(IApplicationContext applicationContext, Type fragmentType) - { - if (!typeof(IFragment).IsAssignableFrom(fragmentType)) - { - return []; - } - - if (ContainsKey(applicationContext?.PluginContext)) - { - var appContextDict = this[applicationContext?.PluginContext]; - - if (appContextDict.ContainsKey(applicationContext)) - { - var fragmentDict = appContextDict[applicationContext]; - - if (fragmentDict.ContainsKey(fragmentType)) - { - return fragmentDict[fragmentType]; - } - } - } - - return []; - } - - /// - /// Returns all fragment contexts for a given plugin context. - /// - /// The plugin context. - /// An IEnumerable of fragment contexts. - public IEnumerable GetFragments(IPluginContext pluginContext) - { - return this.Where(x => x.Key == pluginContext) - .SelectMany(x => x.Value.Values) - .SelectMany(x => x.Values) - .SelectMany(x => x) - .Select(x => x.FragmentContext); - } - } -} diff --git a/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs b/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs deleted file mode 100644 index 93431501..00000000 --- a/src/WebExpress.WebUI/WebFragment/Model/FragmentItem.cs +++ /dev/null @@ -1,75 +0,0 @@ -ο»Ώusing System; -using System.Collections.Generic; -using WebExpress.WebCore.WebApplication; -using WebExpress.WebCore.WebCondition; -using WebExpress.WebCore.WebPlugin; - -namespace WebExpress.WebUI.WebFragment.Model -{ - /// - /// Fragments are components that can be integrated into pages to dynamically expand functionalities. - /// - internal class FragmentItem : IDisposable - { - /// - /// Returns the context of the associated plugin. - /// - public IPluginContext PluginContext { get; set; } - - /// - /// Returns the application context. - /// - public IApplicationContext ApplicationContext { get; set; } - - /// - /// Returns the fragment context. - /// - public IFragmentContext FragmentContext { get; set; } - - /// - /// The type of fragment. - /// - public Type FragmentClass { get; set; } - - /// - /// Returns the section. - /// - public string Section { get; set; } - - /// - /// Returns the scopes. - /// - public IEnumerable Scopes { get; set; } - - /// - /// Returns the conditions that must be met for the component to be active. - /// - public ICollection Conditions { get; set; } - - /// - /// The order of the fragment. - /// - public int Order { get; set; } - - /// - /// Determines whether the component is created once and reused on each execution. - /// - public bool Cache { get; set; } - - /// - /// Performs application-specific tasks related to sharing, returning, or resetting unmanaged resources. - /// - public void Dispose() - { - } - - /// - /// Convert the resource element to a string. - /// - /// The resource element in its string representation. - public override string ToString() - { - return $"Fragment: '{FragmentContext.FragmentId}'"; - } - } -} diff --git a/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs b/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs new file mode 100644 index 00000000..677bc34e --- /dev/null +++ b/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebPage; + +namespace WebExpress.WebUI.WebPage +{ + /// + /// Provides the context for rendering controls within a web page. + /// + public interface IRenderControlContext : IRenderContext + { + /// + /// Adds or replaces a java script if it exists. + /// + /// The key. + /// The java script code. + void AddScript(string key, string code); + + /// + /// Adds a java script. + /// + /// The link of the java script file. + void AddScriptLink(string url); + } +} diff --git a/src/WebExpress.WebUI/WebPage/PageControl.cs b/src/WebExpress.WebUI/WebPage/PageControl.cs index 16968653..42d797fd 100644 --- a/src/WebExpress.WebUI/WebPage/PageControl.cs +++ b/src/WebExpress.WebUI/WebPage/PageControl.cs @@ -1,30 +1,27 @@ ο»Ώusing System.Collections.Generic; -using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebResource; -using WebExpress.WebCore.WebUri; namespace WebExpress.WebUI.WebPage { /// /// A (web) page, which is built from controls. /// - public abstract class PageControl : Page where T : RenderContextControl, new() + public abstract class PageControl : Page where T : VisualTreeControl, new() { /// /// Returns the links to the JavaScript files to be used, which are inserted in the header. /// - protected ICollection HeaderScriptLinks { get; } = new List(); + protected ICollection HeaderScriptLinks { get; } = []; /// /// Returns the links to the css files to use. /// - protected ICollection CssLinks { get; } = new List(); + protected ICollection CssLinks { get; } = []; /// /// Returns the meta information. /// - protected List> Meta { get; } = new List>(); + protected List> Meta { get; } = []; /// /// Initializes a new instance of the class. @@ -34,65 +31,66 @@ public PageControl() } - /// - /// Initialization - /// - /// The context of the resource. - public override void Initialization(IResourceContext context) - { - base.Initialization(context); + ///// + ///// Initialization + ///// + ///// The context of the resource. + //public override void Initialization(IResourceContext context) + //{ + // base.Initialization(context); - var module = ComponentManager.ModuleManager.GetModule(context?.ModuleContext?.ApplicationContext, typeof(Module)); - if (module != null) - { - var contextPath = module.ContextPath; - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/fontawesome.min.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap.min.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/solid.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.expand.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.form.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalform.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalpage.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.more.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.move.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.pagination.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.search.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.selection.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.table.css")); - CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.toolpanel.css")); + // var module = ComponentManager.ModuleManager.GetModule(context?.ModuleContext?.ApplicationContext, typeof(Module)); + // if (module != null) + // { + // var contextPath = module.ContextPath; + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/fontawesome.min.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap.min.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/solid.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.expand.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.form.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalform.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalpage.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.more.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.move.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.pagination.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.search.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.selection.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.table.css")); + // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.toolpanel.css")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); - HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); - } + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); + // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); + // } - Meta.Add(new KeyValuePair("charset", "UTF-8")); - Meta.Add(new KeyValuePair("viewport", "width=device-width, initial-scale=1")); - } + // Meta.Add(new KeyValuePair("charset", "UTF-8")); + // Meta.Add(new KeyValuePair("viewport", "width=device-width, initial-scale=1")); + //} /// /// Processing of the page. /// - /// The context for rendering the page. - public override void Process(T context) + /// The context for rendering the page. + /// The visual tree control to be processed. + public override void Process(IRenderContext renderContext, T visualTree) { - context.VisualTree.CssLinks.AddRange(CssLinks); - context.VisualTree.HeaderScriptLinks.AddRange(HeaderScriptLinks); - context.VisualTree.Meta.AddRange(Meta); + visualTree.CssLinks.AddRange(CssLinks); + visualTree.HeaderScriptLinks.AddRange(HeaderScriptLinks); + visualTree.Meta.AddRange(Meta); } } } diff --git a/src/WebExpress.WebUI/WebPage/RenderContextControl.cs b/src/WebExpress.WebUI/WebPage/RenderContextControl.cs deleted file mode 100644 index 0e370c7e..00000000 --- a/src/WebExpress.WebUI/WebPage/RenderContextControl.cs +++ /dev/null @@ -1,45 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebMessage; -using WebExpress.WebCore.WebPage; - -namespace WebExpress.WebUI.WebPage -{ - public class RenderContextControl : RenderContext - { - /// - /// Returns or sets the visual representation of the page. - /// - public new VisualTreeControl VisualTree - { - get { return base.VisualTree as VisualTreeControl; } - set { base.VisualTree = value; } - } - - /// - /// Initializes a new instance of the class. - /// - public RenderContextControl() - { - VisualTree = new VisualTreeControl(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The page where the control is rendered. - /// The request. - /// The visual tree. - public RenderContextControl(IPage page, Request request, VisualTreeControl visualTree) - : base(page, request, visualTree) - { - } - - /// - /// Copy-Constructor - /// - /// The render context to copy./param> - public RenderContextControl(RenderContext context) - : this(context?.Page, context?.Request, context?.VisualTree as VisualTreeControl) - { - } - } -} diff --git a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs new file mode 100644 index 00000000..e3dd4669 --- /dev/null +++ b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs @@ -0,0 +1,39 @@ +ο»Ώusing WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebPage; + +namespace WebExpress.WebUI.WebPage +{ + /// + /// Provides the context for rendering controls within a web page. + /// + public class RenderControlContext : RenderContext, IRenderControlContext + { + /// + /// Adds or replaces a java script if it exists. + /// + /// The key. + /// The java script code. + void IRenderControlContext.AddScript(string key, string code) + { + } + + /// + /// Adds a java script. + /// + /// The link of the java script file. + void IRenderControlContext.AddScriptLink(string url) + { + + } + + /// + /// Initializes a new instance of the class. + /// + /// >The page context. + /// The request associated with the rendering context. + public RenderControlContext(IPageContext pageContext, Request request) + : base(pageContext, request) + { + } + } +} diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index 3a958a22..03207e19 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -3,7 +3,6 @@ using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebPage; -using WebExpress.WebCore.WebResource; using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebPage @@ -11,12 +10,57 @@ namespace WebExpress.WebUI.WebPage /// /// The content design of a page is realized by controls. /// - public class VisualTreeControl : VisualTree + public class VisualTreeControl : IVisualTree { + /// + /// Returns the title of the html document. + /// + public string Title { get; set; } + + /// + /// Returns the favicons. + /// + public List Favicons { get; } = []; + + /// + /// Returns the internal stylesheet. + /// + public List Styles { get; } = []; + + /// + /// Returns the links to the java script files to be used, which are inserted in the header. + /// + public List HeaderScriptLinks { get; } = []; + + /// + /// Returns the links to the java script files to be used. + /// + public List ScriptLinks { get; } = []; + + /// + /// Returns the links to the java script files to be used, which are inserted in the header. + /// + public List HeaderScripts { get; } = []; + + /// + /// Returns the links to the java script files to be used. + /// + public IDictionary Scripts { get; } = new Dictionary(); + + /// + /// Returns the links to the css files to be used. + /// + public List CssLinks { get; } = []; + + /// + /// Returns the meta information. + /// + public List> Meta { get; } = []; + /// /// Returns the content. /// - public new List Content { get; } = new List(); + public List Content { get; } = []; /// /// Initializes a new instance of the class. @@ -25,26 +69,53 @@ public VisualTreeControl() { } + /// + /// Adds or replaces a java script if it exists. + /// + /// The key. + /// The java script code. + public virtual void AddScript(string key, string code) + { + } + + /// + /// Adds a java script. + /// + /// The link of the java script file. + public virtual void AddScriptLink(string url) + { + } + + /// + /// Adds a java script in the header. + /// + /// The link of the java script file. + public virtual void AddHeaderScriptLinks(string url) + { + } + /// /// Convert to html. /// /// The context for rendering the page. /// The page as an html tree. - public override IHtmlNode Render(RenderContext context) + public virtual IHtmlNode Render(IVisualTreeContext context) { var html = new HtmlElementRootHtml(); - html.Head.Title = InternationalizationManager.I18N(context.Request, context.Page?.Title); + html.Head.Title = I18N.Translate(context.Request, Title); html.Head.Favicons = Favicons?.Select(x => new Favicon(x.Url, x.Mediatype)); html.Head.Styles = Styles; html.Head.Meta = Meta; html.Head.Scripts = HeaderScripts; - html.Body.Elements.AddRange(Content?.Where(x => x.Enable).Select(x => x.Render(context))); - html.Body.Scripts = Scripts.Values.ToList(); + //html.Body.Elements.AddRange(Content?.Where(x => x.Enable).Select(x => x.Render(context))); + html.Body.Scripts = [.. Scripts.Values]; html.Head.CssLinks = CssLinks.Where(x => x != null).Select(x => x.ToString()); html.Head.ScriptLinks = HeaderScriptLinks?.Where(x => x != null).Select(x => x.ToString()); return html; } + + } } diff --git a/src/WebExpress.WebUI/WebSection/SectionControl.cs b/src/WebExpress.WebUI/WebSection/SectionControl.cs deleted file mode 100644 index d48a8edd..00000000 --- a/src/WebExpress.WebUI/WebSection/SectionControl.cs +++ /dev/null @@ -1,38 +0,0 @@ -ο»Ώnamespace WebExpress.WebApp.WebSection -{ - /// - /// Definition of keys to identify sections in wen controls that can be occupied by components. - /// - public static class SectionControl - { - /// - /// Returns the header.preferences section. - /// - public const string HeaderPreferences = "header.preferences"; - - /// - /// Returns the header.primary section. - /// - public const string HeaderPrimary = "header.primary"; - - /// - /// Returns the header.secondary section. - /// - public const string HeaderSecondary = "header.secondary"; - - /// - /// Returns the footer.preferences section. - /// - public const string FooterPreferences = "footer.preferences"; - - /// - /// Returns the footer.primary section. - /// - public const string FooterPrimary = "footer.primary"; - - /// - /// Returns the footer.secondary section. - /// - public const string FooterSecondary = "footer.secondary"; - } -} From 85bdf8818cd0965905837eb9d799acf2ab06cf95 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 14 Dec 2024 20:25:30 +0100 Subject: [PATCH 14/59] refactoring and add tests - ControlDropdownItemLink - FragmentControlDropdownItemLink --- .../TestFragmentControlDropdownItemLink.cs | 22 ++ .../UnitTestControlDropdownItemLink.cs | 195 ++++++++++++++++++ .../WebFragment/UnitTestFragmentManager.cs | 1 + .../WebControl/ControlDropdownItemLink.cs | 162 ++++++++------- .../WebControl/IControlDropdownItem.cs | 3 + .../FragmentControlDropdownItemLink.cs | 58 +++--- 6 files changed, 333 insertions(+), 108 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs new file mode 100644 index 00000000..15050a4e --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlDropdownItemLink : FragmentControlDropdownItemLink + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlDropdownItemLink(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlDropdownItemLink"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs new file mode 100644 index 00000000..63713efa --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs @@ -0,0 +1,195 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the dropdown item link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlControlDropdownItemLink + { + /// + /// Tests the id property of the dropdown item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the dropdown item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the uri property of the dropdown item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the dropdown item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the target property of the dropdown item link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the dropdown item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
                                b", @"b"" data-bs-toggle=""tooltip"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the dropdown item link control. + /// + [Fact] + public void Icon() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemLink() + { + Icon = new PropertyIcon(TypeIcon.Star) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + + /// + /// Tests the content property of the dropdown item link control. + /// + [Fact] + public void Content() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlDropdownItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlDropdownItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlDropdownItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + // test execution + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index 1a63ae80..a2fa8615 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -44,6 +44,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionC), typeof(IScope), @"TestFragmentControlLink")] [InlineData(typeof(TestApplication), typeof(TestSectionD), typeof(IScope), @"TestFragmentControlButtonLink")] [InlineData(typeof(TestApplication), typeof(TestSectionE), typeof(IScope), @"")] + [InlineData(typeof(TestApplication), typeof(TestSectionF), typeof(IScope), @"TestFragmentControlDropdownItemLink")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index ddca8dc4..b90f0074 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -1,88 +1,92 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlDropdownItemLink : ControlLink, IControlDropdownItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlDropdownItemLink(string id = null) -// : base(id) -// { -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a dropdown item link control. + /// + public class ControlDropdownItemLink : ControlLink, IControlDropdownItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlDropdownItemLink(string id = null, params Control[] content) + : base(id, content) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var param = ""; // GetParams(context?.Page); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext context) + { + var param = ""; // GetParams(context?.Page); -// var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = Css.Concatenate("link", GetClasses()), -// Style = GetStyles(), -// Role = Role, -// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), -// Target = Target, -// Title = I18N.Translate(Title), -// OnClick = OnClick?.ToString() -// }; + var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) + { + Id = Id, + Class = Css.Concatenate("link", GetClasses()), + Style = GetStyles(), + Role = Role, + Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), + Target = Target, + Title = string.IsNullOrEmpty(Title) ? I18N.Translate(context.Request.Culture, Tooltip) : I18N.Translate(context.Request.Culture, Title), + OnClick = OnClick?.ToString() + }; -// if (Icon != null && Icon.HasIcon) -// { -// html.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None) -// }.Render(context)); -// } + if (Icon != null && Icon.HasIcon) + { + html.Elements.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None) + }.Render(context)); + } -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); -// } + if (!string.IsNullOrWhiteSpace(Text)) + { + html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); + } -// if (Modal == null || Modal.Type == TypeModal.None) -// { + if (Modal == null || Modal.Type == TypeModal.None) + { -// } -// else if (Modal.Type == TypeModal.Form) -// { -// html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// html.Href = "#"; -// } -// else if (Modal.Type == TypeModal.Brwoser) -// { -// html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// html.Href = "#"; -// } -// else if (Modal.Type == TypeModal.Modal) -// { -// html.AddUserAttribute("data-bs-toggle", "modal"); -// html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); -// } + } + else if (Modal.Type == TypeModal.Form) + { + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.Href = "#"; + } + else if (Modal.Type == TypeModal.Brwoser) + { + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.Href = "#"; + } + else if (Modal.Type == TypeModal.Modal) + { + html.AddUserAttribute("data-bs-toggle", "modal"); + html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); + } -// if (!string.IsNullOrWhiteSpace(Tooltip)) -// { -// html.AddUserAttribute("data-bs-toggle", "tooltip"); -// } + if (!string.IsNullOrWhiteSpace(Tooltip)) + { + html.AddUserAttribute("data-bs-toggle", "tooltip"); + } -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/IControlDropdownItem.cs b/src/WebExpress.WebUI/WebControl/IControlDropdownItem.cs index 6633c64c..d136a04f 100644 --- a/src/WebExpress.WebUI/WebControl/IControlDropdownItem.cs +++ b/src/WebExpress.WebUI/WebControl/IControlDropdownItem.cs @@ -1,5 +1,8 @@ ο»Ώnamespace WebExpress.WebUI.WebControl { + /// + /// Interface for a dropdown item control. + /// public interface IControlDropdownItem : IControl { } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs index b8b706dc..3b3a8c9d 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs @@ -1,32 +1,32 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragment -// { -// /// -// /// Liefert der Kontext -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragmentControl + { + /// + /// Liefert der Kontext + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlDropdownItemLink(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlDropdownItemLink(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} From a7b688fc971969ac91cff7cc80d21f0b2da57894 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 14 Dec 2024 23:38:54 +0100 Subject: [PATCH 15/59] refactoring and add tests --- .../TestFragmentControlNavigationItemLink.cs | 22 + .../TestFragmentControlPanel.cs | 23 + src/WebExpress.WebUI.Test/TestSectionG.cs | 11 + src/WebExpress.WebUI.Test/TestSectionH.cs | 11 + .../WebControl/UnitTestControlDropdown.cs | 220 +++++++ .../UnitTestControlDropdownItemDivider.cs | 33 + .../UnitTestControlDropdownItemHeader.cs | 56 ++ .../WebControl/UnitTestControlLine.cs | 61 ++ .../UnitTestControlNavigationItemLink.cs | 217 +++++++ .../WebControl/UnitTestControlPanel.cs | 104 ++++ .../WebFragment/UnitTestFragmentManager.cs | 5 +- src/WebExpress.WebUI/WebControl/Control.cs | 2 +- .../WebControl/ControlButton.cs | 20 +- .../WebControl/ControlButtonLink.cs | 18 +- .../WebControl/ControlDropdown.cs | 577 ++++++++---------- .../WebControl/ControlDropdownItemDivider.cs | 78 ++- .../WebControl/ControlDropdownItemHeader.cs | 95 ++- .../WebControl/ControlDropdownItemLink.cs | 18 +- .../WebControl/ControlImage.cs | 5 +- .../WebControl/ControlLine.cs | 104 ++-- .../WebControl/ControlLink.cs | 30 +- .../WebControl/ControlList.cs | 2 +- .../WebControl/ControlListItem.cs | 5 +- .../WebControl/ControlModal.cs | 2 +- .../WebControl/ControlNavigationItemLink.cs | 72 +-- .../WebControl/ControlPanel.cs | 171 ++---- .../WebControl/ControlText.cs | 14 +- src/WebExpress.WebUI/WebControl/IControl.cs | 2 +- .../FragmentControlDropdownItemLink.cs | 2 +- .../WebFragment/FragmentControlList.cs | 2 +- .../FragmentControlNavigationItemLink.cs | 58 +- .../WebFragment/FragmentControlPanel.cs | 61 +- 32 files changed, 1366 insertions(+), 735 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionG.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionH.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs new file mode 100644 index 00000000..41513271 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlNavigationItemLink : FragmentControlNavigationItemLink + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlNavigationItemLink(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlNavigationItemLink"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs new file mode 100644 index 00000000..644aa645 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlPanel : FragmentControlPanel + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlPanel(IFragmentContext fragmentContext) + : base(fragmentContext) + { + AddChild(new ControlText() { Text = "TestFragmentControlPanel" }); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionG.cs b/src/WebExpress.WebUI.Test/TestSectionG.cs new file mode 100644 index 00000000..595c01e9 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionG.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionG : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionH.cs b/src/WebExpress.WebUI.Test/TestSectionH.cs new file mode 100644 index 00000000..afd520d8 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionH.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionH : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs new file mode 100644 index 00000000..a4ad6f3d --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs @@ -0,0 +1,220 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the dropdown control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlDropdown + { + /// + /// Tests the id property of the dropdown control. + /// + [Theory] + [InlineData(null, @"
                                  ")] + [InlineData("id", @"
                                    ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + } + + /// + /// Tests the background color property of the dropdown control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"
                                      ")] + [InlineData(TypeColorButton.Primary, @"
                                        ")] + [InlineData(TypeColorButton.Secondary, @"
                                          ")] + [InlineData(TypeColorButton.Info, @"
                                            ")] + [InlineData(TypeColorButton.Warning, @"
                                              ")] + [InlineData(TypeColorButton.Danger, @"
                                                ")] + [InlineData(TypeColorButton.Light, @"
                                                  ")] + [InlineData(TypeColorButton.Dark, @"
                                                    ")] + public void BackgroundColor(TypeColorButton backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + BackgroundColor = new PropertyColorButton(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the size property of the dropdown control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"
                                                      ")] + [InlineData(TypeSizeButton.Small, @"
                                                        ")] + [InlineData(TypeSizeButton.Large, @"
                                                          ")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the outline property of the dropdown control. + /// + [Theory] + [InlineData(false, @"
                                                            ")] + [InlineData(true, @"
                                                              ")] + public void Outline(bool outline, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Outline = outline, + BackgroundColor = new PropertyColorButton(TypeColorButton.Primary) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the block property of the dropdown control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"
                                                                ")] + [InlineData(TypeBlockButton.Block, @"
                                                                  ")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the toogle property of the dropdown control. + /// + [Theory] + [InlineData(TypeToggleDropdown.None, @"
                                                                    ")] + [InlineData(TypeToggleDropdown.Toggle, @"
                                                                      ")] + public void Toogle(TypeToggleDropdown toogle, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Toogle = toogle + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                        ")] + [InlineData("abc", @"
                                                                          ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                            ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                              ")] + [InlineData("abc", @"
                                                                                ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                  ")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Tooltip = tooltip, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + ///// + ///// Tests the add function of the dropdown control. + ///// + //[Theory] + //[InlineData(typeof(ControlText), @"
                                                                                  ")] + //[InlineData(typeof(ControlLink), @"
                                                                                  ")] + //[InlineData(typeof(ControlImage), @"
                                                                                  ")] + //public void Add(Type child, string expected) + //{ + // // preconditions + // UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + // var context = UnitTestControlFixture.CrerateRenderContextMock(); + // var childInstance = Activator.CreateInstance(child, [null]) as IControl; + // var control = new ControlDropdown(); + + // // test execution + // control.AddChild(childInstance); + + // var html = control.Render(context); + + // Assert.Equal(expected, html.Trim()); + //} + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs new file mode 100644 index 00000000..6b010cf9 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs @@ -0,0 +1,33 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the dropdown control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlDropdownItemDivider + { + /// + /// Tests the id property of the dropdown item divider control. + /// + [Theory] + [InlineData(null, @"
                                                                                  ")] + [InlineData("id", @"
                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemDivider(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs new file mode 100644 index 00000000..e7a74083 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs @@ -0,0 +1,56 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the dropdown control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlDropdownItemHeader + { + /// + /// Tests the id property of the dropdown item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                • ")] + [InlineData("id", @"
                                                                                • ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemHeader(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + } + + /// + /// Tests the text property of the dropdown item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                • ")] + [InlineData("abc", @"
                                                                                • abc
                                                                                • ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                • WebExpress.WebUI
                                                                                • ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdownItemHeader() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs new file mode 100644 index 00000000..92d83aaa --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs @@ -0,0 +1,61 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the image control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlLine + { + /// + /// Tests the id property of the line control. + /// + [Theory] + [InlineData(null, @"
                                                                                  ")] + [InlineData("id", @"
                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLine(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the color property of the line control. + /// + [Theory] + [InlineData(TypeColorLine.Default, @"
                                                                                  ")] + [InlineData(TypeColorLine.Primary, @"
                                                                                  ")] + [InlineData(TypeColorLine.Secondary, @"
                                                                                  ")] + [InlineData(TypeColorLine.Info, @"
                                                                                  ")] + [InlineData(TypeColorLine.Warning, @"
                                                                                  ")] + [InlineData(TypeColorLine.Danger, @"
                                                                                  ")] + [InlineData(TypeColorLine.Light, @"
                                                                                  ")] + [InlineData(TypeColorLine.Dark, @"
                                                                                  ")] + public void Color(TypeColorLine color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLine() + { + Color = new PropertyColorLine(color) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs new file mode 100644 index 00000000..863c07fd --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs @@ -0,0 +1,217 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the navigation item link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlNavigationItemLink + { + /// + /// Tests the id property of the navigation item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the navigation item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the uri property of the navigation item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the navigation item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the target property of the navigation item link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the navigation item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
                                                                                  b", @"b"" data-bs-toggle=""tooltip"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the navigation item link control. + /// + [Fact] + public void Icon() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + Icon = new PropertyIcon(TypeIcon.Star) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + + /// + /// Tests the no wrap property of the navigation item link control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void NoWrap(bool noWrap, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemLink() + { + NoWrap = noWrap + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the content property of the navigation item link control. + /// + [Fact] + public void Content() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlNavigationItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlNavigationItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlNavigationItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + // test execution + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs new file mode 100644 index 00000000..3c1d0024 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -0,0 +1,104 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanel + { + /// + /// Tests the id property of the panel control. + /// + [Theory] + [InlineData(null, @"
                                                                                  ")] + [InlineData("id", @"
                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanel(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the direction property of the panel control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                  ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                  ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                  ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                  ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                  ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanel() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the fluid property of the panel control. + /// + [Theory] + [InlineData(TypePanelContainer.Default, @"
                                                                                  ")] + [InlineData(TypePanelContainer.None, @"
                                                                                  ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                  ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanel() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the add child function of the panel control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                  ")] + [InlineData(typeof(ControlLink), @"
                                                                                  ")] + [InlineData(typeof(ControlImage), @"
                                                                                  ")] + public void AddChildren(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanel(); + + // test execution + control.AddChild(childInstance); + + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index a2fa8615..aa2478c7 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -1,6 +1,5 @@ ο»Ώusing WebExpress.WebCore.WebScope; using WebExpress.WebUI.Test.Fixture; -using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebFragment { @@ -45,6 +44,8 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionD), typeof(IScope), @"TestFragmentControlButtonLink")] [InlineData(typeof(TestApplication), typeof(TestSectionE), typeof(IScope), @"")] [InlineData(typeof(TestApplication), typeof(TestSectionF), typeof(IScope), @"TestFragmentControlDropdownItemLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionG), typeof(IScope), @"TestFragmentControlNavigationItemLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionH), typeof(IScope), @"
                                                                                  TestFragmentControlPanel
                                                                                  ")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions @@ -53,7 +54,7 @@ public void Render(Type applicationType, Type sectionType, Type scopeType, strin var renderContext = UnitTestControlFixture.CrerateRenderContextMock(application, [scopeType]); // test execution - var html = componentHub.FragmentManager.Render(renderContext, sectionType); + var html = componentHub.FragmentManager.Render(renderContext, sectionType); Assert.NotNull(html); Assert.NotEmpty(html); diff --git a/src/WebExpress.WebUI/WebControl/Control.cs b/src/WebExpress.WebUI/WebControl/Control.cs index a62d2ad6..f918d1af 100644 --- a/src/WebExpress.WebUI/WebControl/Control.cs +++ b/src/WebExpress.WebUI/WebControl/Control.cs @@ -301,6 +301,6 @@ protected string GetStyles() ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public abstract IHtmlNode Render(IRenderControlContext context); + public abstract IHtmlNode Render(IRenderControlContext renderContext); } } diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index b21dc4e5..fe9c05d9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -46,7 +46,7 @@ public TypeBlockButton Block /// /// Returns the content. /// - public IEnumerable Content { get; private set; } = []; + public IEnumerable Content { get; private set; } = []; /// /// Returns or sets the text. @@ -82,7 +82,7 @@ public TypeActive Active /// /// The id of the control. /// The child controls to be added to the button. - public ControlButton(string id = null, params Control[] content) + public ControlButton(string id = null, params IControl[] content) : base(id) { Size = TypeSizeButton.Default; @@ -94,7 +94,7 @@ public ControlButton(string id = null, params Control[] content) ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { var html = new HtmlElementFieldButton() { @@ -109,7 +109,7 @@ public override IHtmlNode Render(IRenderControlContext context) if (Icon != null && Icon.HasIcon) { - html.Elements.Add(new ControlIcon() + html.Add(new ControlIcon() { Icon = Icon, Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin @@ -120,12 +120,12 @@ public override IHtmlNode Render(IRenderControlContext context) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); + }.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(Text)) { - html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); + html.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); } if (!string.IsNullOrWhiteSpace(OnClick?.ToString())) @@ -135,7 +135,7 @@ public override IHtmlNode Render(IRenderControlContext context) if (Content.Any()) { - html.Elements.AddRange(Content.Select(x => x.Render(context))); + html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) @@ -144,18 +144,18 @@ public override IHtmlNode Render(IRenderControlContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.WebUI.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.WebUI.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; } else if (Modal.Type == TypeModal.Modal) { html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(context)); + return new HtmlList(html, Modal.Modal.Render(renderContext)); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index df96948f..aac4c497 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -25,7 +25,7 @@ public class ControlButtonLink : ControlButton ///
                                                                                  /// The id of the control. /// The child controls to be added to the button. - public ControlButtonLink(string id = null, params Control[] content) + public ControlButtonLink(string id = null, params IControl[] content) : base(id, content) { Classes.Add("btn"); @@ -36,7 +36,7 @@ public ControlButtonLink(string id = null, params Control[] content) ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { var text = I18N.Translate(Text); @@ -53,7 +53,7 @@ public override IHtmlNode Render(IRenderControlContext context) if (Icon != null && Icon.HasIcon) { - html.Elements.Add(new ControlIcon() + html.Add(new ControlIcon() { Icon = Icon, Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin @@ -64,17 +64,17 @@ public override IHtmlNode Render(IRenderControlContext context) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(context)); + }.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(text)) { - html.Elements.Add(new HtmlText(text)); + html.Add(new HtmlText(text)); } if (Content.Any()) { - html.Elements.AddRange(Content.Select(x => x.Render(context))); + html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) @@ -83,12 +83,12 @@ public override IHtmlNode Render(IRenderControlContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Modal) @@ -96,7 +96,7 @@ public override IHtmlNode Render(IRenderControlContext context) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(context)); + return new HtmlList(html, Modal.Modal.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(Tooltip)) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs index d33df261..d668dd25 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs @@ -1,318 +1,259 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlDropdown : Control, IControlNavigationItem -// { -// /// -// /// Returns or sets the content. -// /// -// public List Items { get; private set; } = new List(); - -// /// -// /// Returns or sets the background color. -// /// -// public new PropertyColorButton BackgroundColor -// { -// get => (PropertyColorButton)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); -// } - -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeButton Size -// { -// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the outline property -// /// -// public bool Outline { get; set; } - -// /// -// /// Returns or sets whether the button should take up the full width. -// /// -// public TypeBlockButton Block -// { -// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets an indicator that indicates that a menu is present. -// /// -// public TypeToggleDropdown Toogle -// { -// get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the tooltip. -// /// -// public string Title { get; set; } - -// /// -// /// Returns or sets the value. -// /// -// public string Value { get; set; } - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Returns or sets the activation status of the button. -// /// -// public TypeActive Active -// { -// get => (TypeActive)GetProperty(TypeActive.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the orientation of the menu. -// /// -// public TypeAlignmentDropdownMenu AlignmentMenu -// { -// get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the image. -// /// -// public string Image { get; set; } - -// /// -// /// Returns or sets the height. -// /// -// public new int Height { get; set; } = -1; - -// /// -// /// Returns or sets the width. -// /// -// public new int Width { get; set; } = -1; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlDropdown(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlDropdown(string id, params IControlDropdownItem[] content) -// : base(id) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlDropdown(params IControlDropdownItem[] content) -// : base(null) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlDropdown(string id, IEnumerable content) -// : base(id) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlDropdown(IEnumerable content) -// : base(null) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Adds a new item. -// /// -// /// The item. -// public void Add(IControlDropdownItem item) -// { -// Items.Add(item); -// } - -// /// -// /// Adds a new separator. -// /// -// public void AddSeperator() -// { -// Items.Add(null); -// } - -// /// -// /// Adds a new head. -// /// -// /// The headline text. -// public void AddHeader(string text) -// { -// Items.Add(new ControlDropdownItemHeader() { Text = text }); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Size = TypeSizeButton.Default; -// } - -// /// -// /// Adds items. -// /// -// /// The items which should be added. -// public void Add(params IControlDropdownItem[] item) -// { -// Items.AddRange(item); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("dropdown", Margin.ToClass()), -// Role = Role -// }; - -// if (Image == null) -// { -// var button = new HtmlElementFieldButton() -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), -// Style = GetStyles(), -// Title = Title -// }; -// button.AddUserAttribute("data-bs-toggle", "dropdown"); -// button.AddUserAttribute("aria-expanded", "false"); - -// if (Icon != null && Icon.HasIcon) -// { -// button.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// button.Elements.Add(new HtmlText(Text)); -// } - -// html.Elements.Add(button); -// } -// else -// { -// var button = new HtmlElementMultimediaImg() -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), -// Style = GetStyles(), -// Src = Image.ToString() -// }; -// button.AddUserAttribute("data-bs-toggle", "dropdown"); -// button.AddUserAttribute("aria-expanded", "false"); - -// if (Height > 0) -// { -// button.Height = Height; -// } - -// if (Width > 0) -// { -// button.Width = Width; -// } - -// html.Elements.Add(button); -// } - -// html.Elements.Add -// ( -// new HtmlElementTextContentUl -// ( -// Items.Select -// ( -// x => -// x == null || x is ControlDropdownItemDivider || x is ControlLine ? -// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : -// x is ControlDropdownItemHeader ? -// x.Render(context) : -// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } -// ) -// ) -// { -// Class = Css.Concatenate -// ( -// "dropdown-menu", -// AlignmentMenu.ToClass() -// ) -// } -// ); - -// var modals = Items.Where(x => x is ControlDropdownItemLink) -// .Select(x => x as ControlDropdownItemLink) -// .Select(x => x.Modal) -// .Where(x => x.Type == TypeModal.Modal) -// .Select(x => x.Modal.Render(context)); - -// return new HtmlList(html, modals); -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a dropdown control that can contain multiple items. + /// + public class ControlDropdown : Control, IControlNavigationItem + { + private readonly List _items = []; + + /// + /// Returns the items in the dropdown. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the background color. + /// + public new PropertyColorButton BackgroundColor + { + get => (PropertyColorButton)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); + } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the outline property. + /// + public bool Outline { get; set; } + + /// + /// Returns or sets whether the button should take up the full width. + /// + public TypeBlockButton Block + { + get => (TypeBlockButton)GetProperty(TypeBlockButton.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets an indicator that indicates that a menu is present. + /// + public TypeToggleDropdown Toogle + { + get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the tooltip. + /// + public string Tooltip { get; set; } + + /// + /// Returns or sets the value. + /// + public string Value { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the activation status of the button. + /// + public TypeActive Active + { + get => (TypeActive)GetProperty(TypeActive.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the orientation of the menu. + /// + public TypeAlignmentDropdownMenu AlignmentMenu + { + get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the image. + /// + public string Image { get; set; } + + /// + /// Returns or sets the height. + /// + public new int Height { get; set; } = -1; + + /// + /// Returns or sets the width. + /// + public new int Width { get; set; } = -1; + + /// + /// Initializes a new instance of the class with the specified id and items. + /// + /// The id of the control. + /// The items to be added to the dropdown. + public ControlDropdown(string id = null, params IControlDropdownItem[] items) + : base(id) + { + _items.AddRange(items); + + Size = TypeSizeButton.Default; + } + /// + /// Adds one or more items to the dropdown. + /// + /// The item. + public void Add(params IControlDropdownItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds a new separator. + /// + public void AddSeperator() + { + _items.Add(null); + } + + /// + /// Adds a new head. + /// + /// The headline text. + public void AddHeader(string text) + { + _items.Add(new ControlDropdownItemHeader() { Text = text }); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("dropdown", Margin.ToClass()), + Role = Role + }; + + if (Image == null) + { + var button = new HtmlElementFieldButton() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles(), + Title = I18N.Translate(Tooltip) + }; + button.AddUserAttribute("data-bs-toggle", "dropdown"); + button.AddUserAttribute("aria-expanded", "false"); + + if (Icon != null && Icon.HasIcon) + { + button.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + button.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); + } + + html.Add(button); + } + else + { + var button = new HtmlElementMultimediaImg() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles(), + Src = Image.ToString() + }; + button.AddUserAttribute("data-bs-toggle", "dropdown"); + button.AddUserAttribute("aria-expanded", "false"); + + if (Height > 0) + { + button.Height = Height; + } + + if (Width > 0) + { + button.Width = Width; + } + + html.Add(button); + } + + html.Add + ( + new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } + ).ToArray() + ) + { + Class = Css.Concatenate + ( + "dropdown-menu", + AlignmentMenu.ToClass() + ) + } + ); + + var modals = Items.Where(x => x is ControlDropdownItemLink) + .Select(x => x as ControlDropdownItemLink) + .Select(x => x.Modal) + .Where(x => x.Type == TypeModal.Modal) + .Select(x => x.Modal.Render(renderContext)); + + return new HtmlList(html, modals); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs index ec1e7d13..52afab0c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs @@ -1,43 +1,41 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlDropdownItemDivider : Control, IControlDropdownItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlDropdownItemDivider(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a divider item within a dropdown control. + /// + /// + /// This class is used to create a visual separation between dropdown items. + /// + public class ControlDropdownItemDivider : Control, IControlDropdownItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlDropdownItemDivider(string id = null) + : base(id) + { + } -// /// -// /// Initialization -// /// -// private void Init() -// { -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("dropdown-divider", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("dropdown-divider", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs index 85ff81cc..401ba198 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs @@ -1,59 +1,42 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlDropdownItemHeader : Control, IControlDropdownItem -// { -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a header item in a dropdown control. + /// + public class ControlDropdownItemHeader : Control, IControlDropdownItem + { + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlDropdownItemHeader(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlDropdownItemHeader(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlDropdownItemHeader(string id, string text) -// : base(id) -// { -// Text = text; - -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementTextContentLi(new HtmlText(Text)) -// { -// Id = Id, -// Class = Css.Concatenate("dropdown-header", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))) + { + Id = Id, + Class = Css.Concatenate("dropdown-header", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index b90f0074..ba242aee 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -15,7 +15,7 @@ public class ControlDropdownItemLink : ControlLink, IControlDropdownItem ///
                                                                                  /// The id of the control. /// The content of the html element. - public ControlDropdownItemLink(string id = null, params Control[] content) + public ControlDropdownItemLink(string id = null, params IControl[] content) : base(id, content) { } @@ -25,11 +25,11 @@ public ControlDropdownItemLink(string id = null, params Control[] content) ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { var param = ""; // GetParams(context?.Page); - var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) + var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), @@ -37,13 +37,13 @@ public override IHtmlNode Render(IRenderControlContext context) Role = Role, Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), Target = Target, - Title = string.IsNullOrEmpty(Title) ? I18N.Translate(context.Request.Culture, Tooltip) : I18N.Translate(context.Request.Culture, Title), + Title = string.IsNullOrEmpty(Title) ? I18N.Translate(renderContext.Request.Culture, Tooltip) : I18N.Translate(renderContext.Request.Culture, Title), OnClick = OnClick?.ToString() }; if (Icon != null && Icon.HasIcon) { - html.Elements.Add(new ControlIcon() + html.Add(new ControlIcon() { Icon = Icon, Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin @@ -53,12 +53,12 @@ public override IHtmlNode Render(IRenderControlContext context) PropertySpacing.Space.None, PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None) - }.Render(context)); + }.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(Text)) { - html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); + html.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); } if (Modal == null || Modal.Type == TypeModal.None) @@ -67,12 +67,12 @@ public override IHtmlNode Render(IRenderControlContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Modal) diff --git a/src/WebExpress.WebUI/WebControl/ControlImage.cs b/src/WebExpress.WebUI/WebControl/ControlImage.cs index db50087a..f1eac7c6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlImage.cs +++ b/src/WebExpress.WebUI/WebControl/ControlImage.cs @@ -33,10 +33,9 @@ public class ControlImage : Control ///
                                                                                  /// The id of the control. /// The image source. - public ControlImage(string id = null, string uri = null) + public ControlImage(string id = null) : base(id) { - Uri = uri; } /// @@ -44,7 +43,7 @@ public ControlImage(string id = null, string uri = null) /// /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { Classes.Add(HorizontalAlignment.ToClass()); diff --git a/src/WebExpress.WebUI/WebControl/ControlLine.cs b/src/WebExpress.WebUI/WebControl/ControlLine.cs index fbefac34..b0f2cc98 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLine.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLine.cs @@ -1,62 +1,52 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlLine : Control, IControlSplitButtonItem, IControlDropdownItem -// { -// /// -// /// Returns or sets the text color. -// /// -// public new PropertyColorText TextColor { get; private set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control line that can be used as a split button item or a dropdown item. + /// + public class ControlLine : Control, IControlSplitButtonItem, IControlDropdownItem + { + /// + /// Returns or set the background color. + /// + public new PropertyColorBackground BackgroundColor { get; private set; } -// /// -// /// Returns or set the background color. -// /// -// public new PropertyColorBackground BackgroundColor { get; private set; } + /// + /// Returns or sets the color. + /// + public PropertyColorLine Color + { + get => (PropertyColorLine)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } -// /// -// /// Returns or sets the color. -// /// -// public PropertyColorLine Color -// { -// get => (PropertyColorLine)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlLine(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlLine(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentHr() + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentHr() -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index 31d62d42..33e5405a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -68,7 +68,7 @@ public TypeTextDecoration Decoration /// /// Returns or sets the content. /// - public IEnumerable Content { get; private set; } = []; + public IEnumerable Content { get; private set; } = []; /// /// Returns or sets the parameters that apply to the link. @@ -98,7 +98,7 @@ public PropertySizeText Size /// /// The id of the control. /// The content of the html element. - public ControlLink(string id = null, params Control[] content) + public ControlLink(string id = null, params IControl[] content) : base(id) { Content = content; @@ -136,15 +136,15 @@ private string GetParams(Request request) } /// - /// Convert to html. + /// Convert the control to HTML. /// - /// The context in which the control is rendered. - /// The control as html. - public override IHtmlNode Render(IRenderControlContext context) + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) { - var param = GetParams(context?.Request); + var param = GetParams(renderContext?.Request); - var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) + var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), @@ -152,13 +152,13 @@ public override IHtmlNode Render(IRenderControlContext context) Role = Role, Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), Target = Target, - Title = string.IsNullOrEmpty(Title) ? I18N.Translate(context.Request.Culture, Tooltip) : I18N.Translate(context.Request.Culture, Title), + Title = string.IsNullOrEmpty(Title) ? I18N.Translate(renderContext.Request.Culture, Tooltip) : I18N.Translate(renderContext.Request.Culture, Title), OnClick = OnClick?.ToString() }; if (Icon != null && Icon.HasIcon) { - html.Elements.Add(new ControlIcon() + html.Add(new ControlIcon() { Icon = Icon, Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin @@ -168,12 +168,12 @@ public override IHtmlNode Render(IRenderControlContext context) PropertySpacing.Space.None, PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None) - }.Render(context)); + }.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(Text)) { - html.Elements.Add(new HtmlText(I18N.Translate(context.Request.Culture, Text))); + html.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); } if (Modal == null || Modal.Type == TypeModal.None) @@ -182,12 +182,12 @@ public override IHtmlNode Render(IRenderControlContext context) } else if (Modal.Type == TypeModal.Form) { - html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Brwoser) { - html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + html.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? html.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; html.Href = "#"; } else if (Modal.Type == TypeModal.Modal) @@ -195,7 +195,7 @@ public override IHtmlNode Render(IRenderControlContext context) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(context)); + return new HtmlList(html, Modal.Modal.Render(renderContext)); } if (!string.IsNullOrWhiteSpace(Tooltip)) diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index 2a3d0cf3..03480bf3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -81,7 +81,7 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable break; } - var html = new HtmlElementTextContentUl(li) + var html = new HtmlElementTextContentUl(li.ToArray()) { Id = Id, Class = Css.Concatenate("", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index acb78cc4..a4b3bf8e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -49,11 +49,10 @@ public ControlListItem(string id = null, IEnumerable content = null) /// Convert the control to HTML. ///
                                                                                  /// The context in which the control is rendered. - /// The list entries. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { - return new HtmlElementTextContentLi(Content.Where(x => x.Enable).Select(x => x.Render(context))) + return new HtmlElementTextContentLi(Content.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index 42d0334a..850a20ca 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -117,7 +117,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Class = "modal-header" }; - var body = new HtmlElementTextContentDiv(from x in Content select x.Render(renderContext)) + var body = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) { Class = "modal-body" }; diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs index a3e76ff3..8cacb780 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs @@ -1,39 +1,43 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlNavigationItemLink : ControlLink, IControlNavigationItem -// { -// /// -// /// Verhindert den Zeilenumbruch -// /// -// public bool NoWrap { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a navigation item link control. + /// + public class ControlNavigationItemLink : ControlLink, IControlNavigationItem + { + /// + /// Prevents line break. + /// + public bool NoWrap { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlNavigationItemLink(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlNavigationItemLink(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = base.Render(context); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = base.Render(renderContext); -// if (NoWrap) -// { -// html.AddClass("text-nowrap"); -// } + if (NoWrap) + { + html.AddClass("text-nowrap"); + } -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 8d5fb7a5..84814098 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -1,111 +1,74 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanel : Control -// { -// /// -// /// Returns or sets the content. -// /// -// public List Content { get; private set; } = new List(); +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. + /// + public class ControlPanel : Control + { + private readonly List _children = []; -// /// -// /// Returns or sets the arrangement of the content. -// /// -// public TypeDirection Direction -// { -// get => (TypeDirection)GetProperty(TypeDirection.Default); -// set => SetProperty(value, () => value.ToClass()); -// } + // + // Returns the child controls contained within the control panel. + // + public IEnumerable Children => _children; -// /// -// /// Fixed or full-width adjustment. -// /// -// public TypePanelContainer Fluid -// { -// get => (TypePanelContainer)GetProperty(TypePanelContainer.None); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the arrangement of the content. + /// + public TypeDirection Direction + { + get => (TypeDirection)GetProperty(TypeDirection.Default); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanel(string id = null) -// : base(id) -// { -// } + /// + /// Fixed or full-width adjustment. + /// + public TypePanelContainer Fluid + { + get => (TypePanelContainer)GetProperty(TypePanelContainer.None); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlPanel(params IControl[] content) -// : this() -// { -// Content.AddRange(content.Where(x => x != null)); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel. + public ControlPanel(string id = null, params IControl[] children) + : base(id) + { + _children.AddRange(children.Where(x => x != null)); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlPanel(ICollection content) -// : this() -// { -// Content.AddRange(content.Where(x => x != null)); -// } + /// + /// Adds one or more child controls to the control panel. + /// + /// The child controls to add. + public void AddChild(params IControl[] children) + { + _children.AddRange(children); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanel(string id, params IControl[] content) -// : this(id) -// { -// Content.AddRange(content.Where(x => x != null)); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanel(string id, IEnumerable content) -// : this(id) -// { -// Content.AddRange(content.Where(x => x != null)); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanel(string id, List content) -// : base(id) -// { -// Content = content; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = GetClasses(), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentDiv(Children.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlText.cs b/src/WebExpress.WebUI/WebControl/ControlText.cs index 22811dd1..1b44f573 100644 --- a/src/WebExpress.WebUI/WebControl/ControlText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlText.cs @@ -46,19 +46,11 @@ public PropertySizeText Size ///
                                                                                  public string Title { get; set; } - /// - /// Initializes a new instance of the class. - /// - public ControlText() - : base(null) - { - } - /// /// Initializes a new instance of the class. /// /// The id of the control. - public ControlText(string id) + public ControlText(string id = null) : base(id) { } @@ -68,9 +60,9 @@ public ControlText(string id) ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext context) + public override IHtmlNode Render(IRenderControlContext renderContext) { - var text = I18N.Translate(context?.Request.Culture, Text); + var text = I18N.Translate(renderContext?.Request.Culture, Text); HtmlElement html; switch (Format) diff --git a/src/WebExpress.WebUI/WebControl/IControl.cs b/src/WebExpress.WebUI/WebControl/IControl.cs index e430fa90..133f6ae3 100644 --- a/src/WebExpress.WebUI/WebControl/IControl.cs +++ b/src/WebExpress.WebUI/WebControl/IControl.cs @@ -18,6 +18,6 @@ public interface IControl ///
                                                                                  /// The context in which the control is rendered. /// An HTML node representing the rendered control. - IHtmlNode Render(IRenderControlContext context); + IHtmlNode Render(IRenderControlContext renderContext); } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs index 3b3a8c9d..1f6e69c0 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebFragment public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragmentControl { /// - /// Liefert der Kontext + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; private set; } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs index a88e3b51..06db9524 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlList.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebFragment public abstract class FragmentControlList : ControlList, IFragmentControl { /// - /// Gets the context of the fragment. + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs index f36db8c7..ff8ee0b1 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlNavigationItemLink.cs @@ -1,32 +1,32 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlNavigationItemLink : ControlNavigationItemLink, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + public class FragmentControlNavigationItemLink : ControlNavigationItemLink, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlNavigationItemLink(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlNavigationItemLink(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs index 9d29a954..4ee8e6e4 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanel.cs @@ -1,32 +1,35 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlPanel : ControlPanel, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a control panel that is part of a web fragment and implements the IFragmentControl interface. + /// + public class FragmentControlPanel : ControlPanel, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlPanel(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlPanel(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} From bb284333bdd2e64ec35183aee12aacbc025fc65b Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Wed, 18 Dec 2024 21:28:04 +0100 Subject: [PATCH 16/59] add tests --- .../WebControl/UnitTestControlDropdown.cs | 130 +++++++++++++++--- 1 file changed, 108 insertions(+), 22 deletions(-) diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs index a4ad6f3d..607c92f0 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs @@ -194,27 +194,113 @@ public void Tooltip(string tooltip, string expected) Assert.Equal(expected, html.Trim()); } - ///// - ///// Tests the add function of the dropdown control. - ///// - //[Theory] - //[InlineData(typeof(ControlText), @"
                                                                                  ")] - //[InlineData(typeof(ControlLink), @"
                                                                                  ")] - //[InlineData(typeof(ControlImage), @"
                                                                                  ")] - //public void Add(Type child, string expected) - //{ - // // preconditions - // UnitTestControlFixture.CreateAndRegisterComponentHubMock(); - // var context = UnitTestControlFixture.CrerateRenderContextMock(); - // var childInstance = Activator.CreateInstance(child, [null]) as IControl; - // var control = new ControlDropdown(); - - // // test execution - // control.AddChild(childInstance); - - // var html = control.Render(context); - - // Assert.Equal(expected, html.Trim()); - //} + /// + /// Tests the value property of the dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                                    ")] + [InlineData("abc", @"
                                                                                      ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                        ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Value = value, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the dropdown control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                          ")] + [InlineData(TypeIcon.Star, @"
                                                                                            ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the active property of the dropdown control. + /// + [Theory] + [InlineData(TypeActive.None, @"
                                                                                              ")] + [InlineData(TypeActive.Active, @"
                                                                                                ")] + [InlineData(TypeActive.Disabled, @"
                                                                                                  ")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + Active = active + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the alignment menu property of the dropdown control. + /// + [Theory] + [InlineData(TypeAlignmentDropdownMenu.Default, @"
                                                                                                    ")] + [InlineData(TypeAlignmentDropdownMenu.Right, @"
                                                                                                      ")] + public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown() + { + AlignmentMenu = alignmentMenu + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + } + + /// + /// Tests the add function of the dropdown control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlDropdown(); + + // test execution + control.Add(new ControlDropdownItemLink() { Text = "abc" }); + + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } } } From 9c1238017443e0fa890b147ddfab6e75a627c80a Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Thu, 19 Dec 2024 21:40:13 +0100 Subject: [PATCH 17/59] refactoring and add tests --- .../TestFragmentControlPanelFlexbox.cs | 21 ++ src/WebExpress.WebUI.Test/TestSectionI.cs | 11 + .../WebControl/UnitTestControlPanelFlexbox.cs | 201 ++++++++++++++++++ .../WebFragment/UnitTestFragmentManager.cs | 1 + ...gmentManager.cs => UnitTestPageManager.cs} | 2 +- .../WebControl/ControlPanelFlexbox.cs | 175 ++++++--------- .../WebFragment/FragmentControlButtonLink.cs | 2 +- .../WebFragment/FragmentControlImage.cs | 2 +- .../WebFragment/FragmentControlLink.cs | 2 +- .../FragmentControlPanelFlexbox.cs | 61 +++--- .../WebFragment/FragmentControlText.cs | 2 +- 11 files changed, 341 insertions(+), 139 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionI.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs rename src/WebExpress.WebUI.Test/WebPage/{UnitTestFragmentManager.cs => UnitTestPageManager.cs} (96%) diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs new file mode 100644 index 00000000..f3589583 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs @@ -0,0 +1,21 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlPanelFlexbox : FragmentControlPanelFlexbox + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlPanelFlexbox(IFragmentContext fragmentContext) + : base(fragmentContext) + { + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionI.cs b/src/WebExpress.WebUI.Test/TestSectionI.cs new file mode 100644 index 00000000..0018d41c --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionI.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionI : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs new file mode 100644 index 00000000..fcd07659 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs @@ -0,0 +1,201 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel flexbox control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelFlexbox + { + /// + /// Tests the id property of the panel flexbox control. + /// + [Theory] + [InlineData(null, @"
                                                                                                      ")] + [InlineData("id", @"
                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the direction property of the panel flexbox control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the fluid property of the panel flexbox control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the layout property of the panel flexbox control. + /// + [Theory] + [InlineData(TypeLayoutFlexbox.None, @"
                                                                                                      ")] + [InlineData(TypeLayoutFlexbox.Default, @"
                                                                                                      ")] + [InlineData(TypeLayoutFlexbox.Inline, @"
                                                                                                      ")] + public void Layout(TypeLayoutFlexbox layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Layout = layout, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the justify property of the panel flexbox control. + /// + [Theory] + [InlineData(TypeJustifiedFlexbox.None, @"
                                                                                                      ")] + [InlineData(TypeJustifiedFlexbox.Start, @"
                                                                                                      ")] + [InlineData(TypeJustifiedFlexbox.Around, @"
                                                                                                      ")] + [InlineData(TypeJustifiedFlexbox.Between, @"
                                                                                                      ")] + [InlineData(TypeJustifiedFlexbox.End, @"
                                                                                                      ")] + public void Justify(TypeJustifiedFlexbox justify, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Justify = justify, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the align property of the panel flexbox control. + /// + [Theory] + [InlineData(TypeAlignFlexbox.None, @"
                                                                                                      ")] + [InlineData(TypeAlignFlexbox.Start, @"
                                                                                                      ")] + [InlineData(TypeAlignFlexbox.Stretch, @"
                                                                                                      ")] + [InlineData(TypeAlignFlexbox.Baseline, @"
                                                                                                      ")] + [InlineData(TypeAlignFlexbox.End, @"
                                                                                                      ")] + public void Align(TypeAlignFlexbox align, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Align = align, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the wrap property of the panel flexbox control. + /// + [Theory] + [InlineData(TypeWrap.None, @"
                                                                                                      ")] + [InlineData(TypeWrap.Wrap, @"
                                                                                                      ")] + [InlineData(TypeWrap.Nowrap, @"
                                                                                                      ")] + [InlineData(TypeWrap.Reverse, @"
                                                                                                      ")] + public void Wrap(TypeWrap wrap, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFlexbox() + { + Wrap = wrap, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the add child function of the panel flexbox control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                      ")] + public void AddChildren(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelFlexbox(); + + // test execution + control.AddChild(childInstance); + + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index aa2478c7..365caf44 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -46,6 +46,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionF), typeof(IScope), @"TestFragmentControlDropdownItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionG), typeof(IScope), @"TestFragmentControlNavigationItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionH), typeof(IScope), @"
                                                                                                      TestFragmentControlPanel
                                                                                                      ")] + [InlineData(typeof(TestApplication), typeof(TestSectionI), typeof(IScope), @"
                                                                                                      ")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions diff --git a/src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs similarity index 96% rename from src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs rename to src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs index c59818fd..48e5b42a 100644 --- a/src/WebExpress.WebUI.Test/WebPage/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs @@ -3,7 +3,7 @@ namespace WebExpress.WebUI.Test.WebPage { /// - /// Test the fragment manager. + /// Test the page manager. /// [Collection("NonParallelTests")] public class UnitTestPageManager diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs index 28032fc0..e72a4d9d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs @@ -1,113 +1,78 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelFlexbox : ControlPanel -// { -// /// -// /// Returns or sets whether the items should be displayed inline. -// /// -// public virtual TypeLayoutFlexbox Layout -// { -// get => (TypeLayoutFlexbox)GetProperty(TypeLayoutFlexbox.Default); -// set => SetProperty(value, () => value.ToClass()); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that uses a flexbox layout to arrange its child controls. + /// + public class ControlPanelFlexbox : ControlPanel + { + /// + /// Returns or sets whether the items should be displayed inline. + /// + public virtual TypeLayoutFlexbox Layout + { + get => (TypeLayoutFlexbox)GetProperty(TypeLayoutFlexbox.Default); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets the horizontal alignment of the items. -// /// -// public virtual TypeJustifiedFlexbox Justify -// { -// get => (TypeJustifiedFlexbox)GetProperty(TypeJustifiedFlexbox.Start); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the horizontal alignment of the items. + /// + public virtual TypeJustifiedFlexbox Justify + { + get => (TypeJustifiedFlexbox)GetProperty(TypeJustifiedFlexbox.Start); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Bestimmt, ob Specifies or sets the vertical orientation of the items. -// /// -// public virtual TypeAlignFlexbox Align -// { -// get => (TypeAlignFlexbox)GetProperty(TypeAlignFlexbox.Start); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the vertical orientation of the items. + /// + public virtual TypeAlignFlexbox Align + { + get => (TypeAlignFlexbox)GetProperty(TypeAlignFlexbox.Start); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets the overflow behavior of the items. -// /// -// public virtual TypeWrap Wrap -// { -// get => (TypeWrap)GetProperty(TypeWrap.Nowrap); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the overflow behavior of the items. + /// + public virtual TypeWrap Wrap + { + get => (TypeWrap)GetProperty(TypeWrap.Nowrap); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelFlexbox(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The flexbox items. + public ControlPanelFlexbox(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The flexbox items. -// public ControlPanelFlexbox(string id, params IControl[] content) -// : base(id, content) -// { -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The flexbox items. -// public ControlPanelFlexbox(params IControl[] content) -// : base(null, content) -// { -// } + html.Add(Children.Select(x => x.Render(renderContext))); -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The flexbox items. -// public ControlPanelFlexbox(string id, IEnumerable content) -// : base(id, content) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The flexbox items. -// public ControlPanelFlexbox(IEnumerable content) -// : base(null, content) -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// html.Elements.AddRange(Content.Select(x => x.Render(context))); - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs index 036feddc..e5824697 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlButtonLink.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebFragment public abstract class FragmentControlButtonLink : ControlButtonLink, IFragmentControl { /// - /// Gets the context of the fragment. + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs index 47b9f499..ec981d50 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlImage.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebFragment public abstract class FragmentControlImage : ControlImage, IFragmentControl { /// - /// Gets the context of the fragment. + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs index ead4e4d3..4461a25c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebFragment public abstract class FragmentControlLink : ControlLink, IFragmentControl { /// - /// Gets the context of the fragment. + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs index 69c2589f..92ab8d50 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelFlexbox.cs @@ -1,32 +1,35 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlPanelFlexbox : ControlPanelFlexbox, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a control panel that uses a flexbox layout to arrange its child controls within a fragment context. + /// + public class FragmentControlPanelFlexbox : ControlPanelFlexbox, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlPanelFlexbox(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlPanelFlexbox(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs index 3002c2fb..53ecc60e 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlText.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebFragment public abstract class FragmentControlText : ControlText, IFragmentControl { /// - /// Gets the context of the fragment. + /// Returns the context of the fragment. /// public IFragmentContext FragmentContext { get; } From fa4e3732284f04adc2b0a7dee055b76ac5ee1e4b Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 21 Dec 2024 23:14:30 +0100 Subject: [PATCH 18/59] refactoring and add tests --- .../Fixture/AssertExtensions.cs | 76 +++ .../Fixture/UnitTestControlFixture.cs | 26 - .../TestFragmentControlButtonLink.cs | 2 +- .../TestFragmentControlDropdownItemLink.cs | 2 +- .../TestFragmentControlImage.cs | 2 +- .../TestFragmentControlLink.cs | 2 +- .../TestFragmentControlList.cs | 2 +- .../TestFragmentControlNavigationItemLink.cs | 2 +- .../TestFragmentControlPanel.cs | 2 +- .../TestFragmentControlPanelFlexbox.cs | 2 +- .../TestFragmentControlSplitButtonItemLink.cs | 22 + .../TestFragmentControlText.cs | 2 +- src/WebExpress.WebUI.Test/TestPage.cs | 2 +- src/WebExpress.WebUI.Test/TestSectionE.cs | 11 - src/WebExpress.WebUI.Test/TestSectionF.cs | 11 - .../TestSectionFragmentControlButtonLink.cs | 11 + ...tSectionFragmentControlDropdownItemLink.cs | 11 + .../TestSectionFragmentControlImage.cs | 11 + ...B.cs => TestSectionFragmentControlLink.cs} | 2 +- ...C.cs => TestSectionFragmentControlList.cs} | 2 +- ...ectionFragmentControlNavigationItemLink.cs | 11 + .../TestSectionFragmentControlPanel.cs | 11 + .../TestSectionFragmentControlPanelFlexbox.cs | 11 + ...ctionFragmentControlSplitButtonItemLink.cs | 11 + ...D.cs => TestSectionFragmentControlText.cs} | 2 +- src/WebExpress.WebUI.Test/TestSectionG.cs | 11 - src/WebExpress.WebUI.Test/TestSectionH.cs | 11 - src/WebExpress.WebUI.Test/TestSectionI.cs | 11 - .../{TestSectionA.cs => TestSectionK.cs} | 2 +- .../WebControl/UnitTestControlButton.cs | 17 +- .../WebControl/UnitTestControlDropdown.cs | 4 +- .../UnitTestControlDropdownItemDivider.cs | 4 +- .../UnitTestControlDropdownItemHeader.cs | 4 +- .../UnitTestControlDropdownItemLink.cs | 21 +- .../WebControl/UnitTestControlLink.cs | 19 +- .../WebControl/UnitTestControlModal.cs | 2 +- .../WebControl/UnitTestControlSplitButton.cs | 212 ++++++++ .../UnitTestControlSplitButtonItemDivider.cs | 33 ++ .../UnitTestControlSplitButtonItemHeader.cs | 56 +++ .../UnitTestControlSplitButtonItemLink.cs | 208 ++++++++ .../WebFragment/UnitTestFragmentManager.cs | 22 +- .../WebControl/ControlButton.cs | 30 +- .../WebControl/ControlButtonLink.cs | 4 +- .../WebControl/ControlDropdownItemLink.cs | 2 +- .../WebControl/ControlLink.cs | 26 +- .../WebControl/ControlSplitButton.cs | 453 ++++++++---------- .../ControlSplitButtonItemDivider.cs | 75 ++- .../ControlSplitButtonItemHeader.cs | 95 ++-- .../WebControl/ControlSplitButtonItemLink.cs | 61 ++- .../WebFragment/FragmentControlLink.cs | 2 +- .../FragmentControlSplitButtonItemLink.cs | 60 +-- .../WebFragment/IFragmentControl.cs | 7 + src/WebExpress.WebUI/WebPage/PageControl.cs | 7 +- .../WebPage/RenderControlContext.cs | 9 + .../WebPage/VisualTreeControl.cs | 188 +++++++- 55 files changed, 1348 insertions(+), 557 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlSplitButtonItemLink.cs delete mode 100644 src/WebExpress.WebUI.Test/TestSectionE.cs delete mode 100644 src/WebExpress.WebUI.Test/TestSectionF.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlButtonLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlDropdownItemLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlImage.cs rename src/WebExpress.WebUI.Test/{TestSectionB.cs => TestSectionFragmentControlLink.cs} (75%) rename src/WebExpress.WebUI.Test/{TestSectionC.cs => TestSectionFragmentControlList.cs} (75%) create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlNavigationItemLink.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlPanel.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelFlexbox.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlSplitButtonItemLink.cs rename src/WebExpress.WebUI.Test/{TestSectionD.cs => TestSectionFragmentControlText.cs} (75%) delete mode 100644 src/WebExpress.WebUI.Test/TestSectionG.cs delete mode 100644 src/WebExpress.WebUI.Test/TestSectionH.cs delete mode 100644 src/WebExpress.WebUI.Test/TestSectionI.cs rename src/WebExpress.WebUI.Test/{TestSectionA.cs => TestSectionK.cs} (81%) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs diff --git a/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs new file mode 100644 index 00000000..1c21a1db --- /dev/null +++ b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs @@ -0,0 +1,76 @@ +ο»Ώusing System.Text.RegularExpressions; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.Test.Fixture +{ + /// + /// Provides extension methods for assertions. + /// + public static partial class AssertExtensions + { + /// + /// Gets a regular expression that matches whitespace between '>' and '<' characters. + /// + /// A object that matches whitespace between '>' and '<' characters. + [GeneratedRegex(@">\s+<")] + private static partial Regex WhitespaceRegex(); + + /// + /// Asserts that the actual string is equal to the expected string, allowing for placeholders. + /// + /// The Assert instance (not used, but required for extension method). + /// The expected string with placeholders. + /// The actual string to compare. + public static void EqualWithPlaceholders(string expected, string actual) + { + var str = RemoveLineBreaks(actual); + Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); + } + + /// + /// Asserts that the actual node is equal to the expected string, allowing for placeholders. + /// + /// The Assert instance (not used, but required for extension method). + /// The expected string with placeholders. + /// The actual string to compare. + public static void EqualWithPlaceholders(string expected, IHtmlNode actual) + { + var str = RemoveLineBreaks(actual.ToString()); + Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); + } + + /// + /// Compares two strings, allowing for placeholders in the expected string. + /// + /// The expected string, which may contain '*' as a wildcard character. + /// The actual string to compare against the expected string. + /// True if the actual string matches the expected string with placeholders; otherwise, false. + private static bool AreEqualWithPlaceholders(string expected, string actual) + { + var pattern = "^" + Regex.Escape(expected).Replace(@"\*", ".*") + "$"; + + return Regex.IsMatch(actual, pattern); + } + + /// + /// Removes all line breaks from the input string. + /// + /// The input string from which to remove line breaks. + /// A string with all line breaks removed. + public static string RemoveLineBreaks(string input) + { + if (string.IsNullOrEmpty(input)) + { + return input; + } + + // remove all line breaks + string result = input.Replace("\r\n", "").Replace("\r", "").Replace("\n", ""); + + // remove whitespace of any length between '>' and '<' + result = WhitespaceRegex().Replace(result, "><"); + + return result; + } + } +} diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index 266aed49..740fc93a 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -4,7 +4,6 @@ using System.Net; using System.Reflection; using System.Text; -using System.Text.RegularExpressions; using WebExpress.WebCore; using WebExpress.WebCore.WebApplication; using WebExpress.WebCore.WebComponent; @@ -26,9 +25,6 @@ public partial class UnitTestControlFixture : IDisposable { private static readonly string[] _separator = ["\r\n", "\r", "\n"]; - [GeneratedRegex(@">\s+<")] - private static partial Regex WhitespaceRegex(); - /// /// Initializes a new instance of the class and boot the component manager. /// @@ -184,7 +180,6 @@ public static WebCore.WebMessage.HttpContext CreateHttpContextMock(string conten featureCollection.Set(requestIdentifierFeature); featureCollection.Set(connectionFeature); - var componentManager = CreateComponentHubMock(); var context = new WebCore.WebMessage.HttpContext(featureCollection, CreateHttpServerContextMock()); return context; @@ -242,27 +237,6 @@ public static string GetEmbeddedResource(string fileName) return Encoding.UTF8.GetString(data); } - /// - /// Removes all line breaks from the input string. - /// - /// The input string from which to remove line breaks. - /// A string with all line breaks removed. - public static string RemoveLineBreaks(string input) - { - if (string.IsNullOrEmpty(input)) - { - return input; - } - - // remove all line breaks - string result = input.Replace("\r\n", "").Replace("\r", "").Replace("\n", ""); - - // remove whitespace of any length between '>' and '<' - result = WhitespaceRegex().Replace(result, "><"); - - return result; - } - /// /// Release of unmanaged resources reserved during use. /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs index 03f06241..91e9172e 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlButtonLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlButtonLink : FragmentControlButtonLink { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs index 15050a4e..5c5020b9 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlDropdownItemLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlDropdownItemLink : FragmentControlDropdownItemLink { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs b/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs index ee738ba3..02a93888 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlImage.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlImage : FragmentControlImage { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs index fed17610..7ba35a42 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlLink : FragmentControlLink { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlList.cs b/src/WebExpress.WebUI.Test/TestFragmentControlList.cs index 22d6b0f5..dbda3263 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlList.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlList.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlList : FragmentControlList { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs index 41513271..16e9c8d6 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlNavigationItemLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlNavigationItemLink : FragmentControlNavigationItemLink { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs index 644aa645..abc89e7a 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlPanel : FragmentControlPanel { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs index f3589583..077a456b 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlPanelFlexbox.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlPanelFlexbox : FragmentControlPanelFlexbox { /// diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlSplitButtonItemLink.cs b/src/WebExpress.WebUI.Test/TestFragmentControlSplitButtonItemLink.cs new file mode 100644 index 00000000..4f6a917f --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlSplitButtonItemLink.cs @@ -0,0 +1,22 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlSplitButtonItemLink : FragmentControlSplitButtonItemLink + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlSplitButtonItemLink(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Text = "TestFragmentControlSplitButtonItemLink"; + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlText.cs b/src/WebExpress.WebUI.Test/TestFragmentControlText.cs index bad200f5..696e6432 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlText.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlText.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.Test /// /// A dummy fragment for testing purposes. /// - [Section()] + [Section()] public sealed class TestFragmentControlText : FragmentControlText { /// diff --git a/src/WebExpress.WebUI.Test/TestPage.cs b/src/WebExpress.WebUI.Test/TestPage.cs index a0e747e5..a1e3ee69 100644 --- a/src/WebExpress.WebUI.Test/TestPage.cs +++ b/src/WebExpress.WebUI.Test/TestPage.cs @@ -51,7 +51,7 @@ public void Process(IRenderContext renderContext, VisualTreeControl visualTree) throw new ArgumentNullException(nameof(renderContext), "Parameter cannot be null or empty."); } - visualTree.Content.Add(new ControlText() { Text = "Hello World" }); + visualTree.AddContent(new ControlText() { Text = "Hello World" }); } /// diff --git a/src/WebExpress.WebUI.Test/TestSectionE.cs b/src/WebExpress.WebUI.Test/TestSectionE.cs deleted file mode 100644 index 0d412797..00000000 --- a/src/WebExpress.WebUI.Test/TestSectionE.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebSection; - -namespace WebExpress.WebUI.Test -{ - /// - /// Represents a test section for testing in the web UI. - /// - internal class TestSectionE : ISection - { - } -} diff --git a/src/WebExpress.WebUI.Test/TestSectionF.cs b/src/WebExpress.WebUI.Test/TestSectionF.cs deleted file mode 100644 index 7996eb96..00000000 --- a/src/WebExpress.WebUI.Test/TestSectionF.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebSection; - -namespace WebExpress.WebUI.Test -{ - /// - /// Represents a test section for testing in the web UI. - /// - internal class TestSectionF : ISection - { - } -} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlButtonLink.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlButtonLink.cs new file mode 100644 index 00000000..2fd5326b --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlButtonLink.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlButtonLink : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlDropdownItemLink.cs new file mode 100644 index 00000000..01d18346 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlDropdownItemLink.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlDropdownItemLink : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlImage.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlImage.cs new file mode 100644 index 00000000..878e9214 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlImage.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlImage : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionB.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlLink.cs similarity index 75% rename from src/WebExpress.WebUI.Test/TestSectionB.cs rename to src/WebExpress.WebUI.Test/TestSectionFragmentControlLink.cs index c19681e2..09b9f36a 100644 --- a/src/WebExpress.WebUI.Test/TestSectionB.cs +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlLink.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.Test /// /// Represents a test section for testing in the web UI. /// - internal class TestSectionB : ISection + internal class TestSectionFragmentControlLink : ISection { } } diff --git a/src/WebExpress.WebUI.Test/TestSectionC.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlList.cs similarity index 75% rename from src/WebExpress.WebUI.Test/TestSectionC.cs rename to src/WebExpress.WebUI.Test/TestSectionFragmentControlList.cs index 914219d5..66212ecf 100644 --- a/src/WebExpress.WebUI.Test/TestSectionC.cs +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlList.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.Test /// /// Represents a test section for testing in the web UI. /// - internal class TestSectionC : ISection + internal class TestSectionFragmentControlList : ISection { } } diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlNavigationItemLink.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlNavigationItemLink.cs new file mode 100644 index 00000000..8dc4ca50 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlNavigationItemLink.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlNavigationItemLink : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanel.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanel.cs new file mode 100644 index 00000000..e4eb6c83 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanel.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlPanel : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelFlexbox.cs new file mode 100644 index 00000000..945f4af9 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelFlexbox.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlPanelFlexbox : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlSplitButtonItemLink.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlSplitButtonItemLink.cs new file mode 100644 index 00000000..b6563015 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlSplitButtonItemLink.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlSplitButtonItemLink : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionD.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlText.cs similarity index 75% rename from src/WebExpress.WebUI.Test/TestSectionD.cs rename to src/WebExpress.WebUI.Test/TestSectionFragmentControlText.cs index e1a8e581..2190f5a8 100644 --- a/src/WebExpress.WebUI.Test/TestSectionD.cs +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlText.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.Test /// /// Represents a test section for testing in the web UI. /// - internal class TestSectionD : ISection + internal class TestSectionFragmentControlText : ISection { } } diff --git a/src/WebExpress.WebUI.Test/TestSectionG.cs b/src/WebExpress.WebUI.Test/TestSectionG.cs deleted file mode 100644 index 595c01e9..00000000 --- a/src/WebExpress.WebUI.Test/TestSectionG.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebSection; - -namespace WebExpress.WebUI.Test -{ - /// - /// Represents a test section for testing in the web UI. - /// - internal class TestSectionG : ISection - { - } -} diff --git a/src/WebExpress.WebUI.Test/TestSectionH.cs b/src/WebExpress.WebUI.Test/TestSectionH.cs deleted file mode 100644 index afd520d8..00000000 --- a/src/WebExpress.WebUI.Test/TestSectionH.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebSection; - -namespace WebExpress.WebUI.Test -{ - /// - /// Represents a test section for testing in the web UI. - /// - internal class TestSectionH : ISection - { - } -} diff --git a/src/WebExpress.WebUI.Test/TestSectionI.cs b/src/WebExpress.WebUI.Test/TestSectionI.cs deleted file mode 100644 index 0018d41c..00000000 --- a/src/WebExpress.WebUI.Test/TestSectionI.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebSection; - -namespace WebExpress.WebUI.Test -{ - /// - /// Represents a test section for testing in the web UI. - /// - internal class TestSectionI : ISection - { - } -} diff --git a/src/WebExpress.WebUI.Test/TestSectionA.cs b/src/WebExpress.WebUI.Test/TestSectionK.cs similarity index 81% rename from src/WebExpress.WebUI.Test/TestSectionA.cs rename to src/WebExpress.WebUI.Test/TestSectionK.cs index 8829608d..59b53ca0 100644 --- a/src/WebExpress.WebUI.Test/TestSectionA.cs +++ b/src/WebExpress.WebUI.Test/TestSectionK.cs @@ -5,7 +5,7 @@ namespace WebExpress.WebUI.Test /// /// Represents a test section for testing in the web UI. /// - internal class TestSectionA : ISection + internal class TestSectionK : ISection { } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs index a8e9638a..0c27db73 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs @@ -174,10 +174,10 @@ public void Icon(TypeIcon icon, string expected) } /// - /// Tests the content property of the button control. + /// Tests the add function of the button control. /// [Fact] - public void Content() + public void Add() { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); @@ -185,15 +185,28 @@ public void Content() var control1 = new ControlButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlButton(null); + var control5 = new ControlButton(null); + var control6 = new ControlButton(null); // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var html1 = control1.Render(context); var html2 = control2.Render(context); var html3 = control2.Render(context); + var html4 = control1.Render(context); + var html5 = control2.Render(context); + var html6 = control2.Render(context); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); Assert.Equal(@"", html3.Trim()); + Assert.Equal(@"", html4.Trim()); + Assert.Equal(@"", html5.Trim()); + Assert.Equal(@"", html6.Trim()); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs index 607c92f0..3f9b514b 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -281,7 +281,7 @@ public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expect // test execution var html = control.Render(context); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs index 6b010cf9..1cb96b9d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs @@ -4,7 +4,7 @@ namespace WebExpress.WebUI.Test.WebControl { /// - /// Tests the dropdown control. + /// Tests the dropdown item divider control. /// [Collection("NonParallelTests")] public class UnitTestControlDropdownItemDivider @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs index e7a74083..f1acef47 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs @@ -4,7 +4,7 @@ namespace WebExpress.WebUI.Test.WebControl { /// - /// Tests the dropdown control. + /// Tests the dropdown item header control. /// [Collection("NonParallelTests")] public class UnitTestControlDropdownItemHeader @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.ToString())); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs index 63713efa..5e82365e 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs @@ -8,7 +8,7 @@ namespace WebExpress.WebUI.Test.WebControl /// Tests the dropdown item link control. /// [Collection("NonParallelTests")] - public class UnitTestControlControlDropdownItemLink + public class UnitTestControlDropdownItemLink { /// /// Tests the id property of the dropdown item link control. @@ -170,10 +170,10 @@ public void Icon() } /// - /// Tests the content property of the dropdown item link control. + /// Tests the add function of the dropdown item link control. /// [Fact] - public void Content() + public void Add() { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); @@ -181,15 +181,28 @@ public void Content() var control1 = new ControlDropdownItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlDropdownItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlDropdownItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlDropdownItemLink(null); + var control5 = new ControlDropdownItemLink(null); + var control6 = new ControlDropdownItemLink(null); // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var html1 = control1.Render(context); var html2 = control2.Render(context); - var html3 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); Assert.Equal(@"", html3.Trim()); + Assert.Equal(@"", html4.Trim()); + Assert.Equal(@"", html5.Trim()); + Assert.Equal(@"", html6.Trim()); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs index d0cdeed4..0907f0bb 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs @@ -170,10 +170,10 @@ public void Icon() } /// - /// Tests the content property of the link control. + /// Tests the add function of the link control. /// [Fact] - public void Content() + public void Add() { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); @@ -181,15 +181,28 @@ public void Content() var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlLink(null); + var control5 = new ControlLink(null); + var control6 = new ControlLink(null); // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var html1 = control1.Render(context); var html2 = control2.Render(context); - var html3 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); Assert.Equal(@"", html3.Trim()); + Assert.Equal(@"", html4.Trim()); + Assert.Equal(@"", html5.Trim()); + Assert.Equal(@"", html6.Trim()); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs index 8ec9efce..74acba52 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.Trim())); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs new file mode 100644 index 00000000..3a380ef8 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs @@ -0,0 +1,212 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the split button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlSplitButton + { + /// + /// Tests the id property of the split button control. + /// + [Theory] + [InlineData(null, @"
                                                                                                        ")] + [InlineData("id", @"
                                                                                                          ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButton(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the split button control. + /// + [Theory] + [InlineData(null, @"
                                                                                                          *
                                                                                                          ")] + [InlineData("abc", @"
                                                                                                          *
                                                                                                          ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButton() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the split button control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(TypeSizeButton.Small, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(TypeColorButton.Primary, @"
                                                                                                          + [Theory] + [InlineData(false, TypeColorButton.Default, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(true, TypeColorButton.Default, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(true, TypeColorButton.Primary, @"
                                                                                                          + [Theory] + [InlineData(TypeBlockButton.None, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(TypeBlockButton.Block, @"
                                                                                                          *
                                                                                                          ")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButton() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the split button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                          *
                                                                                                          ")] + [InlineData(TypeIcon.Star, @"
                                                                                                          *
                                                                                                          ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButton() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the split button control. + /// + [Fact] + public void Add() + { + // preconditions + //UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + //var context = UnitTestControlFixture.CrerateRenderContextMock(); + //var control1 = new ControlSplitButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + //var control2 = new ControlSplitButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + //var control3 = new ControlSplitButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + //var control4 = new ControlSplitButton(null); + //var control5 = new ControlSplitButton(null); + //var control6 = new ControlSplitButton(null); + + //// test execution + //control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + //control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + //control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + //var html1 = control1.Render(context); + //var html2 = control2.Render(context); + //var html3 = control2.Render(context); + //var html4 = control1.Render(context); + //var html5 = control2.Render(context); + //var html6 = control2.Render(context); + + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html1.Trim()); + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html2.Trim()); + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html3.Trim()); + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html4.Trim()); + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html5.Trim()); + //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                          *
                                                                                                          ", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs new file mode 100644 index 00000000..ee8ec22c --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs @@ -0,0 +1,33 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the split button item divider control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlSplitButtonItemDivider + { + /// + /// Tests the id property of the split button item divider control. + /// + [Theory] + [InlineData(null, @"
                                                                                                          ")] + [InlineData("id", @"
                                                                                                          ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemDivider(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs new file mode 100644 index 00000000..cff88d8d --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs @@ -0,0 +1,56 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the split button item header control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlSplitButtonItemHeader + { + /// + /// Tests the id property of the split button item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                                        • ")] + [InlineData("id", @"
                                                                                                        • ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemHeader(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the split button item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                                        • ")] + [InlineData("abc", @"
                                                                                                        • abc
                                                                                                        • ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                        • WebExpress.WebUI
                                                                                                        • ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemHeader() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs new file mode 100644 index 00000000..38e65ddc --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs @@ -0,0 +1,208 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the split button item link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlSplitButtonItemLink + { + /// + /// Tests the id property of the split button item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the text property of the split button item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the uri property of the split button item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the split button item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the target property of the split button item link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the tooltip property of the split button item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
                                                                                                          b", @"b"" data-bs-toggle=""tooltip"">")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the split button item link control. + /// + [Fact] + public void Icon() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonItemLink() + { + Icon = new PropertyIcon(TypeIcon.Star) + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + + /// + /// Tests the add function of the split button item link control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlLink(null); + var control5 = new ControlLink(null); + var control6 = new ControlLink(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + Assert.Equal(@"", html4.Trim()); + Assert.Equal(@"", html5.Trim()); + Assert.Equal(@"", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index 365caf44..e41d5f98 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -38,15 +38,17 @@ public void Id(Type applicationType, Type fragmentType, string id) /// Test the render function of the fragment manager. ///
                                                                                                          [Theory] - [InlineData(typeof(TestApplication), typeof(TestSectionA), typeof(IScope), @"

                                                                                                          TestFragmentControlText

                                                                                                          ")] - [InlineData(typeof(TestApplication), typeof(TestSectionB), typeof(IScope), @"
                                                                                                          ")] - [InlineData(typeof(TestApplication), typeof(TestSectionC), typeof(IScope), @"TestFragmentControlLink")] - [InlineData(typeof(TestApplication), typeof(TestSectionD), typeof(IScope), @"TestFragmentControlButtonLink")] - [InlineData(typeof(TestApplication), typeof(TestSectionE), typeof(IScope), @"")] - [InlineData(typeof(TestApplication), typeof(TestSectionF), typeof(IScope), @"TestFragmentControlDropdownItemLink")] - [InlineData(typeof(TestApplication), typeof(TestSectionG), typeof(IScope), @"TestFragmentControlNavigationItemLink")] - [InlineData(typeof(TestApplication), typeof(TestSectionH), typeof(IScope), @"
                                                                                                          TestFragmentControlPanel
                                                                                                          ")] - [InlineData(typeof(TestApplication), typeof(TestSectionI), typeof(IScope), @"
                                                                                                          ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlText), typeof(IScope), @"

                                                                                                          TestFragmentControlText

                                                                                                          ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlList), typeof(IScope), @"
                                                                                                          ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlLink), typeof(IScope), @"TestFragmentControlLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlButtonLink), typeof(IScope), @"TestFragmentControlButtonLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlImage), typeof(IScope), @"")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlDropdownItemLink), typeof(IScope), @"TestFragmentControlDropdownItemLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlNavigationItemLink), typeof(IScope), @"TestFragmentControlNavigationItemLink")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanel), typeof(IScope), @"
                                                                                                          TestFragmentControlPanel
                                                                                                          ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelFlexbox), typeof(IScope), @"
                                                                                                          ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlSplitButtonItemLink), typeof(IScope), @"TestFragmentControlSplitButtonItemLink")] + //[InlineData(typeof(TestApplication), typeof(TestSectionK), typeof(IScope), @"TestFragmentControl")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions @@ -59,7 +61,7 @@ public void Render(Type applicationType, Type sectionType, Type scopeType, strin Assert.NotNull(html); Assert.NotEmpty(html); - Assert.Equal(expected, UnitTestControlFixture.RemoveLineBreaks(html.FirstOrDefault()?.ToString())); + AssertExtensions.EqualWithPlaceholders(expected, html.FirstOrDefault()?.ToString()); } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index fe9c05d9..2c7a4b6b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -11,6 +11,8 @@ namespace WebExpress.WebUI.WebControl ///
                                                                                                          public class ControlButton : Control, IControlButton { + private readonly List _children = []; + /// /// Returns or sets the color. /// @@ -44,9 +46,9 @@ public TypeBlockButton Block } /// - /// Returns the content. + /// Returns the children. /// - public IEnumerable Content { get; private set; } = []; + public IEnumerable Children => _children; /// /// Returns or sets the text. @@ -86,7 +88,25 @@ public ControlButton(string id = null, params IControl[] content) : base(id) { Size = TypeSizeButton.Default; - Content = content ?? []; + _children.AddRange(content); + } + + /// + /// Adds one or more content. + /// + /// The content to add to the button. + public void Add(params IControl[] items) + { + _children.AddRange(items); + } + + /// + /// Adds one or more items to the split button. + /// + /// The items to add to the split button. + public void Add(IEnumerable items) + { + _children.AddRange(items); } /// @@ -133,9 +153,9 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("onclick", OnClick?.ToString()); } - if (Content.Any()) + if (_children.Count != 0) { - html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); + html.Add(_children.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index aac4c497..94c1a951 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -72,9 +72,9 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.Add(new HtmlText(text)); } - if (Content.Any()) + if (Children.Any()) { - html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); + html.Add(Children.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index ba242aee..91a5b226 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -29,7 +29,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) { var param = ""; // GetParams(context?.Page); - var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(Children.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index 33e5405a..ab4c19a7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -12,6 +12,8 @@ namespace WebExpress.WebUI.WebControl /// public class ControlLink : Control, IControlLink { + private readonly List _children = []; + /// /// Returns or sets whether the link is active or not. /// @@ -68,7 +70,7 @@ public TypeTextDecoration Decoration /// /// Returns or sets the content. /// - public IEnumerable Content { get; private set; } = []; + public IEnumerable Children => _children; /// /// Returns or sets the parameters that apply to the link. @@ -101,7 +103,25 @@ public PropertySizeText Size public ControlLink(string id = null, params IControl[] content) : base(id) { - Content = content; + _children.AddRange(content); + } + + /// + /// Adds one or more children to the link. + /// + /// The children to add to the split button. + public void Add(params IControl[] children) + { + _children.AddRange(children); + } + + /// + /// Adds one or more children to the link. + /// + /// The children to add to the split button. + public void Add(IEnumerable children) + { + _children.AddRange(children); } /// @@ -144,7 +164,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) { var param = GetParams(renderContext?.Request); - var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(_children.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs index 4bbdbaf8..76e8407e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs @@ -1,244 +1,209 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlSplitButton : Control, IControlButton -// { -// /// -// /// Returns or sets the background color. -// /// -// public new PropertyColorButton BackgroundColor -// { -// get => (PropertyColorButton)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); -// } - -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeButton Size -// { -// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the outline property -// /// -// public bool Outline { get; set; } - -// /// -// /// Returns or sets whether the button should take up the full width. -// /// -// public TypeBlockButton Block -// { -// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the value. -// /// -// public string Value { get; set; } - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Returns or sets the activation status of the button. -// /// -// public TypeActive Active -// { -// get => (TypeActive)GetProperty(TypeActive.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets a modal dialogue. -// /// -// public PropertyModal Modal { get; set; } = new PropertyModal(); - -// /// -// /// Returns or sets the content. -// /// -// protected List Items { get; private set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlSplitButton(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlSplitButton(params IControlSplitButtonItem[] items) -// : base(null) -// { -// Items.AddRange(items); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlSplitButton(string id, params IControlSplitButtonItem[] items) -// : base(id) -// { -// Items.AddRange(items); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlSplitButton(string id, IEnumerable items) -// : base(id) -// { -// Items.AddRange(items); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlSplitButton(IEnumerable items) -// : base(null) -// { -// Items.AddRange(items); - -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Size = TypeSizeButton.Default; -// //BackgroundColor = LayoutSchema.ButtonBackground; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var button = new HtmlElementFieldButton() -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), -// Style = GetStyles() -// }; - -// if (Icon != null && Icon.HasIcon) -// { -// button.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// button.Elements.Add(new HtmlText(Text)); -// } - -// if (Modal == null || Modal.Type == TypeModal.None) -// { - -// } -// else if (Modal.Type == TypeModal.Form) -// { -// button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// } -// else if (Modal.Type == TypeModal.Brwoser) -// { -// button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// } -// else if (Modal.Type == TypeModal.Modal) -// { -// button.AddUserAttribute("data-bs-toggle", "modal"); -// button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); -// } - -// var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), -// Style = GetStyles(), -// DataToggle = "dropdown" -// }; -// dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); -// dropdownButton.AddUserAttribute("aria-expanded", "false"); - -// var dropdownElements = new HtmlElementTextContentUl -// ( -// Items.Select -// ( -// x => -// x == null || x is ControlDropdownItemDivider || x is ControlLine ? -// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : -// x is ControlDropdownItemHeader ? -// x.Render(context) : -// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } -// ) -// ) -// { -// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" -// }; - -// var html = new HtmlElementTextContentDiv -// ( -// Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(context)) : button, -// dropdownButton, -// dropdownElements -// ) -// { -// Class = Css.Concatenate -// ( -// "btn-group ", -// Margin.ToClass(), -// (Block == TypeBlockButton.Block ? "btn-block" : "") -// ), -// Role = Role -// }; - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a split button control that can contain multiple items. + /// + public class ControlSplitButton : Control, IControlButton + { + private readonly List _items = []; + + /// + /// Returns or sets the background color. + /// + public new PropertyColorButton BackgroundColor + { + get => (PropertyColorButton)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); + } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the outline property + /// + public bool Outline { get; set; } + + /// + /// Returns or sets whether the button should take up the full width. + /// + public TypeBlockButton Block + { + get => (TypeBlockButton)GetProperty(TypeBlockButton.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the value. + /// + public string Value { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the activation status of the button. + /// + public TypeActive Active + { + get => (TypeActive)GetProperty(TypeActive.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets a modal dialogue. + /// + public PropertyModal Modal { get; set; } = new PropertyModal(); + + /// + /// Returns or sets the content. + /// + public IEnumerable Items => _items; + + /// + /// Initializes a new instance of the class. + /// + /// The content of the html element. + public ControlSplitButton(string id = null, params IControlSplitButtonItem[] items) + : base(id) + { + Size = TypeSizeButton.Default; + _items.AddRange(items); + } + + /// + /// Adds one or more items to the split button. + /// + /// The items to add to the split button. + public void Add(params IControlSplitButtonItem[] items) + { + _items.AddRange(items); + } + /// + /// Adds one or more items to the split button. + /// + /// The items to add to the split button. + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var button = new HtmlElementFieldButton() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles() + }; + + if (Icon != null && Icon.HasIcon) + { + button.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + button.Add(new HtmlText(Text)); + } + + if (Modal == null || Modal.Type == TypeModal.None) + { + + } + else if (Modal.Type == TypeModal.Form) + { + button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + } + else if (Modal.Type == TypeModal.Brwoser) + { + button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + } + else if (Modal.Type == TypeModal.Modal) + { + button.AddUserAttribute("data-bs-toggle", "modal"); + button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); + } + + var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_toggle", + Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), + Style = GetStyles(), + DataToggle = "dropdown" + }; + dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); + dropdownButton.AddUserAttribute("aria-expanded", "false"); + + var dropdownElements = new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } + ).ToArray() + ) + { + Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" + }; + + var html = new HtmlElementTextContentDiv + ( + Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(renderContext)) : button, + dropdownButton, + dropdownElements + ) + { + Id = Id, + Class = Css.Concatenate + ( + "btn-group", + Margin.ToClass(), + (Block == TypeBlockButton.Block ? "btn-block" : "") + ), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs index a0b526a5..b11113be 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs @@ -1,43 +1,38 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlSplitButtonItemDivider : Control, IControlSplitButtonItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlSplitButtonItemDivider(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a divider item in a split button control. + /// + public class ControlSplitButtonItemDivider : Control, IControlSplitButtonItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlSplitButtonItemDivider(string id = null) + : base(id) + { + } -// /// -// /// Initialization -// /// -// private void Init() -// { -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("dropdown-divider", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("dropdown-divider", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs index 03c6e5f7..9f2d7017 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs @@ -1,59 +1,42 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlSplitButtonItemHeader : Control, IControlSplitButtonItem -// { -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a header item in a split button control. + /// + public class ControlSplitButtonItemHeader : Control, IControlSplitButtonItem + { + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlSplitButtonItemHeader(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlSplitButtonItemHeader(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlSplitButtonItemHeader(string id, string text) -// : base(id) -// { -// Text = text; - -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementTextContentLi(new HtmlText(Text)) -// { -// Id = Id, -// Class = Css.Concatenate("dropdown-header", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext?.Request?.Culture, Text))) + { + Id = Id, + Class = Css.Concatenate("dropdown-header", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs index fdb15cc7..2aa50120 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs @@ -1,35 +1,30 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlSplitButtonItemLink : ControlLink, IControlSplitButtonItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlSplitButtonItemLink(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a link item within a split button control. + /// + public class ControlSplitButtonItemLink : ControlLink, IControlSplitButtonItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlSplitButtonItemLink(string id = null) + : base(id) + { + } -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return base.Render(context); -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return base.Render(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs index 4461a25c..9fd1f5e6 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlLink.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.WebFragment /// /// Represents a link control fragment that can be processed and rendered within a web page. /// - public abstract class FragmentControlLink : ControlLink, IFragmentControl + public abstract class FragmentControlLink : ControlLink, IFragmentControl { /// /// Returns the context of the fragment. diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs index 6ca1f47f..29ee2d6d 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlSplitButtonItemLink.cs @@ -1,32 +1,34 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlSplitButtonItemLink : ControlSplitButtonItemLink, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a link item within a split button control that is part of a fragment. + /// + public class FragmentControlSplitButtonItemLink : ControlSplitButtonItemLink, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlSplitButtonItemLink(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlSplitButtonItemLink(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs index 3fa39b57..7d513c28 100644 --- a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs +++ b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs @@ -4,6 +4,13 @@ namespace WebExpress.WebUI.WebFragment { + /// + /// Represents a fragment interface with a generic type parameter. + /// + public interface IFragmentControl : IFragmentControl + { + } + /// /// Represents a fragment interface with a generic type parameter. /// diff --git a/src/WebExpress.WebUI/WebPage/PageControl.cs b/src/WebExpress.WebUI/WebPage/PageControl.cs index 42d797fd..a6b936c2 100644 --- a/src/WebExpress.WebUI/WebPage/PageControl.cs +++ b/src/WebExpress.WebUI/WebPage/PageControl.cs @@ -1,4 +1,5 @@ ο»Ώusing System.Collections.Generic; +using System.Linq; using WebExpress.WebCore.WebPage; namespace WebExpress.WebUI.WebPage @@ -88,9 +89,9 @@ public PageControl() /// The visual tree control to be processed. public override void Process(IRenderContext renderContext, T visualTree) { - visualTree.CssLinks.AddRange(CssLinks); - visualTree.HeaderScriptLinks.AddRange(HeaderScriptLinks); - visualTree.Meta.AddRange(Meta); + visualTree.AddCssLink(CssLinks.ToArray()); + visualTree.AddHeaderScriptLink(HeaderScriptLinks.ToArray()); + //visualTree.AddMeta(Meta); } } } diff --git a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs index e3dd4669..1cc68a9b 100644 --- a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs +++ b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs @@ -26,6 +26,15 @@ void IRenderControlContext.AddScriptLink(string url) } + /// + /// Initializes a new instance of the class. + /// + /// The render context. + public RenderControlContext(IRenderContext renderContext) + : base(renderContext?.PageContext, renderContext?.Request) + { + } + /// /// Initializes a new instance of the class. /// diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index 03207e19..7872b72a 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -12,6 +12,16 @@ namespace WebExpress.WebUI.WebPage /// public class VisualTreeControl : IVisualTree { + private readonly List _favicons = []; + private readonly List _styles = []; + private readonly List _headerScriptLinks = []; + private readonly List _scriptLinks = []; + private readonly List _headerScripts = []; + private readonly Dictionary _scripts = []; + private readonly List _cssLinks = []; + private readonly Dictionary _meta = []; + private readonly List _content = []; + /// /// Returns the title of the html document. /// @@ -20,47 +30,47 @@ public class VisualTreeControl : IVisualTree /// /// Returns the favicons. /// - public List Favicons { get; } = []; + public IEnumerable Favicons => _favicons; /// /// Returns the internal stylesheet. /// - public List Styles { get; } = []; + public IEnumerable Styles => _styles; /// /// Returns the links to the java script files to be used, which are inserted in the header. /// - public List HeaderScriptLinks { get; } = []; + public IEnumerable HeaderScriptLinks => _headerScriptLinks; /// /// Returns the links to the java script files to be used. /// - public List ScriptLinks { get; } = []; + public IEnumerable ScriptLinks => _scriptLinks; /// /// Returns the links to the java script files to be used, which are inserted in the header. /// - public List HeaderScripts { get; } = []; + public IEnumerable HeaderScripts => _headerScripts; /// /// Returns the links to the java script files to be used. /// - public IDictionary Scripts { get; } = new Dictionary(); + public IReadOnlyDictionary Scripts => _scripts; /// /// Returns the links to the css files to be used. /// - public List CssLinks { get; } = []; + public IEnumerable CssLinks => _cssLinks; /// /// Returns the meta information. /// - public List> Meta { get; } = []; + public IReadOnlyDictionary Meta => _meta; /// /// Returns the content. /// - public List Content { get; } = []; + public IEnumerable Content => _content; /// /// Initializes a new instance of the class. @@ -70,28 +80,168 @@ public VisualTreeControl() } /// - /// Adds or replaces a java script if it exists. + /// Adds a favicon to the web application. + /// + /// The URL of the favicon. + /// The media type of the favicon. + public void AddFavicon(string url, string mediatype) + { + _favicons.Add(new Favicon(url, mediatype)); + } + + /// + /// Removes a favicon from the web application. + /// + /// The URL of the favicon to remove. + public void RemoveFavicon(string url) + { + _favicons.RemoveAll(x => x.Url.Equals(url)); + } + + /// + /// Adds one or more styles to the head. + /// + /// The styles to add. + public void AddStyle(params string[] styles) + { + _styles.AddRange(styles); + } + + /// + /// Removes a style from the head. + /// + /// The style to remove. + public void RemoveStyle(string style) + { + _styles.RemoveAll(x => x.Equals(style)); + } + + /// + /// Adds one or more URLs to the list of header script links. + /// + /// The URLs of the script to add. + public void AddHeaderScriptLink(params string[] urls) + { + _headerScriptLinks.AddRange(urls); + } + + /// + /// Removes a URL from the list of header script links. + /// + /// The URL of the script to remove. + public void RemoveHeaderScriptLink(string url) + { + _headerScriptLinks.RemoveAll(x => x.Equals(url)); + } + + /// + /// Adds one or more URLs to the list of script links. + /// + /// The URLs of the script to add. + public void AddScriptLink(params string[] urls) + { + _scriptLinks.AddRange(urls); + } + + /// + /// Removes a URL from the list of script links. + /// + /// The URL of the script to remove. + public void RemoveScriptLink(string url) + { + _scriptLinks.RemoveAll(x => x.Equals(url)); + } + + /// + /// Adds one or more URLs to the list of header scripts. + /// + /// The URLs of the script to add. + public void AddHeaderScript(params string[] urls) + { + _headerScripts.AddRange(urls); + } + + /// + /// Removes a URL from the list of header scripts. + /// + /// The URL of the script to remove. + public void RemoveHeaderScript(string url) + { + _headerScripts.RemoveAll(x => x.Equals(url)); + } + + /// + /// Adds a script to the collection. If a script with the same identifier already exists, it will be overwritten. + /// + /// The identifier of the script. + /// The script content. + public void AddScript(string id, string script) + { + _scripts[id] = script; + } + + /// + /// Removes a script from the collection. + /// + /// The identifier of the script to remove. + public void RemoveScript(string id) + { + _scripts.Remove(id); + } + + /// + /// Adds one or more URLs to the list of CSS links. + /// + /// The URLs of the CSS file to add. + public void AddCssLink(params string[] urls) + { + _cssLinks.AddRange(urls); + } + + /// + /// Removes all CSS links that match the specified URL. + /// + /// The URL of the CSS link to remove. + public void RemoveCssLink(string url) + { + _cssLinks.RemoveAll(x => x.Equals(url)); + } + + /// + /// Adds a meta tag to the collection. If a meta tag with the same name already exists, it will be overwritten. + /// + /// The name of the meta tag. + /// The content of the meta tag. + public void AddMeta(string name, string content) + { + _meta[name] = content; + } + + /// + /// Removes a meta tag from the collection. /// - /// The key. - /// The java script code. - public virtual void AddScript(string key, string code) + /// The name of the meta tag to remove. + public void RemoveMeta(string name) { + _meta.Remove(name); } /// - /// Adds a java script. + /// Adds one or more controls to the content of the page. /// - /// The link of the java script file. - public virtual void AddScriptLink(string url) + /// The controls to add to the content. + public void AddContent(params IControl[] controls) { + _content.AddRange(controls); } /// - /// Adds a java script in the header. + /// Removes a control from the content of the page. /// - /// The link of the java script file. - public virtual void AddHeaderScriptLinks(string url) + /// The control to remove from the content. + public void RemoveContent(IControl control) { + _content.Remove(control); } /// From 7ff8312c7af26a4319779108ff51619d6bec40d1 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 22 Dec 2024 03:48:35 +0100 Subject: [PATCH 19/59] refactoring and add tests --- .../TestFragmentControlTree.cs | 23 + .../TestSectionFragmentControlTree.cs | 11 + .../WebControl/UnitTestControlList.cs | 1 + .../WebControl/UnitTestControlTree.cs | 115 +++++ .../WebControl/UnitTestControlTreeItem.cs | 148 +++++++ .../WebFragment/UnitTestFragmentManager.cs | 2 +- .../WebControl/ControlTree.cs | 273 ++++++------ .../WebControl/ControlTreeItem.cs | 397 ++++++++++-------- .../WebControl/TypeLayoutTree.cs | 6 + .../FragmentControlDropdownItemLink.cs | 3 + .../WebFragment/FragmentControlTree.cs | 62 +-- 11 files changed, 672 insertions(+), 369 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlTree.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlTree.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlTree.cs b/src/WebExpress.WebUI.Test/TestFragmentControlTree.cs new file mode 100644 index 00000000..f13e3dd9 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlTree.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlTree : FragmentControlList + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlTree(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Add(new ControlListItem()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlTree.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlTree.cs new file mode 100644 index 00000000..0a9e814f --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlTree.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlTree : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs index 2e5c0311..8fefdb28 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs @@ -6,6 +6,7 @@ namespace WebExpress.WebUI.Test.WebControl /// /// Tests the list control. /// + [Collection("NonParallelTests")] public class UnitTestControlList : IClassFixture { /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs new file mode 100644 index 00000000..3337e330 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs @@ -0,0 +1,115 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the tree control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTree : IClassFixture + { + /// + /// Tests the id property of the tree control. + /// + [Theory] + [InlineData(null, @"
                                                                                                            ")] + [InlineData("id", @"
                                                                                                              ")] + [InlineData("03C6031F-04A9-451F-B817-EBD6D32F8B0C", @"
                                                                                                                ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTree(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the layout property of the tree control. + /// + [Theory] + [InlineData(TypeLayoutTree.Default, @"
                                                                                                                  ")] + [InlineData(TypeLayoutTree.Simple, @"
                                                                                                                    ")] + [InlineData(TypeLayoutTree.Group, @"
                                                                                                                      ")] + [InlineData(TypeLayoutTree.Horizontal, @"
                                                                                                                        ")] + [InlineData(TypeLayoutTree.Flat, @"
                                                                                                                          ")] + [InlineData(TypeLayoutTree.Flush, @"
                                                                                                                            ")] + [InlineData(TypeLayoutTree.TreeView, @"
                                                                                                                              ")] + public void Layout(TypeLayoutTree layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTree() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the sorted property of the tree control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                ")] + [InlineData(true, @"
                                                                                                                                  ")] + public void Sorted(bool sorted, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTree() + { + Sorted = sorted + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the add function of the tree control. + /// + [Theory] + [MemberData(nameof(GetControlTreeItemsData))] + public void Add(IEnumerable items, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + + // test execution + var control = new ControlTree(null, items.ToArray()); + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Provides test data for the Add method of the UnitTestControlList class. + /// + /// An enumerable collection of object arrays, each containing test data. + public static TheoryData, string> GetControlTreeItemsData() + { + return new TheoryData, string> + { + { new List { new(null, new ControlText() { Text = "Item 1" }) }, @"
                                                                                                                                  • Item 1
                                                                                                                                  " }, + { new List { new("id") }, @"
                                                                                                                                  " }, + { new List { }, "
                                                                                                                                    " } + }; + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs new file mode 100644 index 00000000..cd941f1b --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs @@ -0,0 +1,148 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the tree item control. + /// + public class UnitTestControlTreeItem : IClassFixture + { + /// + /// Tests the id property of the tree item control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                  • ")] + [InlineData("id", @"
                                                                                                                                  • ")] + [InlineData("03C6031F-04A9-451F-B817-EBD6D32F8B0C", @"
                                                                                                                                  • ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem(id) + { + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the active property of the tree item control. + /// + [Theory] + [InlineData(TypeActive.None, @"
                                                                                                                                  • ")] + [InlineData(TypeActive.Active, @"
                                                                                                                                  • ")] + [InlineData(TypeActive.Disabled, @"
                                                                                                                                  • ")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem() + { + Active = active + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the layout property of the tree item control. + /// + [Theory] + [InlineData(TypeLayoutTreeItem.Default, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.Simple, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.Group, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.Horizontal, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.Flat, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.Flush, @"
                                                                                                                                  • ")] + [InlineData(TypeLayoutTreeItem.TreeView, @"
                                                                                                                                  • *
                                                                                                                                  • ")] + public void Layout(TypeLayoutTreeItem layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the expand property of the tree item control. + /// + [Theory] + [InlineData(TypeExpandTree.None, @"
                                                                                                                                  • ")] + [InlineData(TypeExpandTree.Visible, @"
                                                                                                                                  • ")] + [InlineData(TypeExpandTree.Collapse, @"
                                                                                                                                  • ")] + public void Expand(TypeExpandTree expand, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem() + { + Expand = expand + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the tree item control. + /// + [Fact] + public void AddContent() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem() + { + }; + + // test execution + control.Add(new ControlText() { Text = "abc" }); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                  • abc
                                                                                                                                  • ", html); + } + + /// + /// Tests the add function of the tree item control. + /// + [Fact] + public void AddChild() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItem() + { + }; + + // test execution + control.Add(new ControlTreeItem()); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                  • ", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index e41d5f98..7481f00d 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -48,7 +48,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanel), typeof(IScope), @"
                                                                                                                                    TestFragmentControlPanel
                                                                                                                                    ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelFlexbox), typeof(IScope), @"
                                                                                                                                    ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlSplitButtonItemLink), typeof(IScope), @"TestFragmentControlSplitButtonItemLink")] - //[InlineData(typeof(TestApplication), typeof(TestSectionK), typeof(IScope), @"TestFragmentControl")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlTree), typeof(IScope), @"
                                                                                                                                    ")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions diff --git a/src/WebExpress.WebUI/WebControl/ControlTree.cs b/src/WebExpress.WebUI/WebControl/ControlTree.cs index 5b189d08..ed73bdbc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTree.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTree.cs @@ -1,153 +1,120 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlTree : Control -// { -// /// -// /// Returns or sets the layout. -// /// -// public TypeLayoutTree Layout -// { -// get => (TypeLayoutTree)GetProperty(TypeLayoutTree.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Liefert oder setzt die Baumknoten -// /// -// public List Items { get; private set; } = new List(); - -// /// -// /// Bestimm, ob es sich um eine sotrierte oder unsortierte Liste handelt -// /// -// public bool Sorted { get; set; } - -// /// -// /// Zeigt einen Rahmen an oder keinen -// /// -// public bool ShowBorder { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTree(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// Die ListeneintrΓ€ge -// public ControlTree(string id, params ControlTreeItem[] items) -// : base(id) -// { -// Items.AddRange(items); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// Die ListeneintrΓ€ge -// public ControlTree(params ControlTreeItem[] items) -// : this(null, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// Die ListeneintrΓ€ge -// public ControlTree(string id, List items) -// : base(id) -// { -// Items = items; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// Die ListeneintrΓ€ge -// public ControlTree(List items) -// : this(null, items) -// { -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// ShowBorder = true; -// } - -// /// -// /// FΓΌgt ListeneintrΓ€ge hinzu -// /// -// /// Die ListeneintrΓ€ge -// public void Add(IEnumerable items) -// { -// Items.AddRange(items); -// } - -// /// -// /// FΓΌgt ListeneintrΓ€ge hinzu -// /// -// /// Der Listeneintrag -// public void Add(ControlTreeItem item) -// { -// Items.Add(item); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var items = (from x in Items select x.Render(context)).ToList(); - -// switch (Layout) -// { -// case TypeLayoutTree.Horizontal: -// case TypeLayoutTree.Flush: -// case TypeLayoutTree.Group: -// items.ForEach(x => x.AddClass("list-group-item")); -// break; -// } - -// var html = new HtmlElementTextContentUl(items) -// { -// Id = Id, -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// if (Layout == TypeLayoutTree.TreeView) -// { -// context.VisualTree.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); -// for (var i = 0; i < toggler.length; i++) -// { -// toggler[i].addEventListener(""click"", function() { -// this.parentElement.parentElement.querySelector("".tree-treeview-node"").classList.toggle(""tree-node-hide""); -// this.classList.toggle(""tree-treeview-angle-down""); - -// }); -// } -// "); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a tree control that can display hierarchical data. + /// + public class ControlTree : Control + { + private readonly List _nodes = []; + + /// + /// Returns the collection of tree nodes. + /// + public IEnumerable Nodes => _nodes; + + /// + /// Returns or sets the layout. + /// + public TypeLayoutTree Layout + { + get => (TypeLayoutTree)GetProperty(TypeLayoutTree.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets a value indicating whether the tree is sorted. + /// + public bool Sorted { get; set; } + + /// + /// Returns or sets a value indicating whether the tree should display a border. + /// + public bool ShowBorder { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The tree items to be added to the control. + public ControlTree(string id = null, params ControlTreeItem[] items) + : base(id) + { + _nodes.AddRange(items); + ShowBorder = true; + } + + /// + /// Adds the specified tree items to the control. + /// + /// The tree items to be added. + public void Add(params ControlTreeItem[] items) + { + _nodes.AddRange(items); + } + /// + /// Adds the specified tree items to the control. + /// + /// The tree items to be added. + public void Add(IEnumerable items) + { + _nodes.AddRange(items); + } + + /// + /// Removes the specified tree item from the control. + /// + /// The tree item to be removed. + public void Remove(ControlTreeItem item) + { + _nodes.Remove(item); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var items = (from x in Nodes select x.Render(renderContext)).ToList(); + + switch (Layout) + { + case TypeLayoutTree.Horizontal: + case TypeLayoutTree.Flush: + case TypeLayoutTree.Group: + items.ForEach(x => x.AddClass("list-group-item")); + break; + } + + var html = new HtmlElementTextContentUl([.. items]) + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + if (Layout == TypeLayoutTree.TreeView) + { + renderContext.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); + for (var i = 0; i < toggler.length; i++) + { + toggler[i].addEventListener(""click"", function() { + this.parentElement.parentElement.querySelector("".tree-treeview-node"").classList.toggle(""tree-node-hide""); + this.classList.toggle(""tree-treeview-angle-down""); + + }); + } + "); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs index fc80a929..e229710f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs @@ -1,186 +1,211 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlTreeItem : Control -// { -// /// -// /// Returns or sets the content. -// /// -// public List Content { get; private set; } = new List(); - -// /// -// /// Liefert oder setzt die Kinderknoten -// /// -// public List Children { get; private set; } = new List(); - -// /// -// /// Ermittelt ob ein untergeordneter Baumknoten aktiv ist -// /// -// public bool IsAnyChildrenActive -// { -// get -// { -// if (Active == TypeActive.Active) return true; - -// return Children.Where(x => x.IsAnyChildrenActive).Any(); -// } -// } - -// /// -// /// Liefert oder setzt die AtivitΓ€tsstatus des Listenelements -// /// -// public TypeActive Active -// { -// get => (TypeActive)GetProperty(TypeActive.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the layout. -// /// -// public TypeLayoutTreeItem Layout -// { -// get => (TypeLayoutTreeItem)GetProperty(TypeLayoutTreeItem.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Bestimmt, ob die Kinknoten angezeigt werden oder nicht -// /// -// public TypeExpandTree Expand -// { -// get => (TypeExpandTree)GetProperty(TypeExpandTree.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTreeItem(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTreeItem(string id, params Control[] content) -// : this(id) -// { -// Content.AddRange(content.Where(x => !(x is ControlTreeItem))); -// Children.AddRange(content.Where(x => x is ControlTreeItem).Select(x => x as ControlTreeItem)); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlTreeItem(params Control[] content) -// : this(null, content) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTreeItem(string id, List content) -// : this(id, content.ToArray()) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlTreeItem(List content) -// : this(null, content) -// { -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var content = from x in Content select x.Render(context); -// var container = default(HtmlElementTextContentDiv); - -// if (Layout == TypeLayoutTreeItem.TreeView) -// { -// var expander = new HtmlElementTextSemanticsSpan -// { -// Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") -// }; - -// if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) -// { -// expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); -// } - -// container = new HtmlElementTextContentDiv(expander, content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()) -// { -// Class = Css.Concatenate("tree-treeview-container") -// }; -// } -// else -// { -// container = new HtmlElementTextContentDiv(content.Count() > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()); -// } - -// var html = new HtmlElementTextContentLi(container) -// { -// Id = Id, -// Class = Css.Concatenate(Active.ToClass()), -// Style = GetStyles(), -// Role = Role -// }; - -// if (Children.Count > 0) -// { -// var items = (from x in Children select x.Render(context)).ToList(); - -// switch (Layout) -// { -// case TypeLayoutTreeItem.Horizontal: -// case TypeLayoutTreeItem.Flush: -// case TypeLayoutTreeItem.Group: -// items.ForEach(x => x.AddClass("list-group-item")); -// break; -// } - -// var ul = new HtmlElementTextContentUl(items) -// { -// Class = Css.Concatenate(Layout switch -// { -// TypeLayoutTreeItem.TreeView => "tree-treeview-node", -// TypeLayoutTreeItem.Simple => "tree-simple-node", -// _ => Layout.ToClass() -// }, Expand.ToClass()) -// }; - -// html.Elements.Add(ul); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a tree item control that can contain other controls and tree items. + /// + public class ControlTreeItem : Control + { + private readonly List _content = []; + private readonly List _children = []; + + /// + /// Returns the content. + /// + public IEnumerable Content => _content; + + /// + /// Returns the child tree items. + /// + public IEnumerable Children => _children; + + /// + /// Returns a value indicating whether any child tree item is active. + /// + /// + /// true if any child tree item is active; otherwise, false. + /// + public bool IsAnyChildrenActive + { + get + { + if (Active == TypeActive.Active) return true; + + return Children.Where(x => x.IsAnyChildrenActive).Any(); + } + } + + /// + /// Returns or sets the active state of the tree item. + /// + /// + /// The active state of the tree item. + /// + public TypeActive Active + { + get => (TypeActive)GetProperty(TypeActive.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the layout of the tree item. + /// + /// + /// The layout of the tree item. + /// + public TypeLayoutTreeItem Layout + { + get => (TypeLayoutTreeItem)GetProperty(TypeLayoutTreeItem.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the expand state of the tree item. + /// + /// + /// The expand state of the tree item. + /// + public TypeExpandTree Expand + { + get => (TypeExpandTree)GetProperty(TypeExpandTree.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content or child of the node. + public ControlTreeItem(string id = null, params IControl[] content) + : base(id) + { + _content.AddRange(content.Where(x => x is not ControlTreeItem)); + _children.AddRange(content.Where(x => x is ControlTreeItem).Select(x => x as ControlTreeItem)); + } + + /// + /// Adds the specified content to the tree item. + /// + /// The content to add. + public void Add(params IControl[] content) + { + _content.AddRange(content); + } /// + /// Adds the specified content to the tree item. + /// + /// The content to add. + public void Add(IEnumerable content) + { + _content.AddRange(content); + } + /// + /// Adds the specified children to the tree item. + /// + /// The children to add. + public void Add(params ControlTreeItem[] children) + { + _children.AddRange(children); + } + + /// + /// Adds the specified children to the tree item. + /// + /// The children to add. + public void Add(IEnumerable children) + { + _children.AddRange(children); + } + + /// + /// Removes the specified content or children from the tree item. + /// + /// The content or child to remove. + public void Remove(IControl control) + { + if (control is ControlTreeItem) + { + _children.Remove(control as ControlTreeItem); + + return; + } + + _content.Remove(control); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var content = _content.Select(x => x.Render(renderContext)).ToArray(); + var container = default(HtmlElementTextContentDiv); + + if (Layout == TypeLayoutTreeItem.TreeView) + { + var expander = new HtmlElementTextSemanticsSpan + { + Class = Css.Concatenate("tree-treeview-expander", _children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") + }; + + if (_children.Count > 0 && Expand != TypeExpandTree.Collapse) + { + expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); + } + + container = new HtmlElementTextContentDiv(expander, content.Length > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()) + { + Class = Css.Concatenate("tree-treeview-container") + }; + } + else + { + container = new HtmlElementTextContentDiv(content.Length > 1 ? new HtmlElementTextContentDiv(content) : content.FirstOrDefault()) + { + Class = Css.Concatenate("", GetClasses()), + }; + } + + var html = new HtmlElementTextContentLi(container) + { + Id = Id, + Class = Css.Concatenate(Active.ToClass()), + Style = GetStyles(), + Role = Role + }; + + if (_children.Count > 0) + { + var children = _children.Select(x => x.Render(renderContext)).ToList(); + + switch (Layout) + { + case TypeLayoutTreeItem.Horizontal: + case TypeLayoutTreeItem.Flush: + case TypeLayoutTreeItem.Group: + children.ForEach(x => x.AddClass("list-group-item")); + break; + } + + var ul = new HtmlElementTextContentUl([.. children]) + { + Class = Css.Concatenate(Layout switch + { + TypeLayoutTreeItem.TreeView => "tree-treeview-node", + TypeLayoutTreeItem.Simple => "tree-simple-node", + _ => Layout.ToClass() + }, Expand.ToClass()) + }; + + html.Add(ul); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs index 0522d219..3ae7571b 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs @@ -1,5 +1,8 @@ ο»Ώnamespace WebExpress.WebUI.WebControl { + /// + /// Specifies the different types of layout trees. + /// public enum TypeLayoutTree { Default, @@ -11,6 +14,9 @@ public enum TypeLayoutTree TreeView } + /// + /// Provides extension methods for the enum. + /// public static class TypeLayoutTreeExtensions { /// diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs index 1f6e69c0..5c727e3c 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlDropdownItemLink.cs @@ -4,6 +4,9 @@ namespace WebExpress.WebUI.WebFragment { + /// + /// Represents a dropdown item link control within a fragment context. + /// public class FragmentControlDropdownItemLink : ControlDropdownItemLink, IFragmentControl { /// diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs index e0111539..573c09d0 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlTree.cs @@ -1,32 +1,36 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlTree : ControlTree, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a control tree for a fragment, implementing the IFragmentControl interface. + /// + /// The type of control tree. + public class FragmentControlTree : ControlTree, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlTree(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + protected FragmentControlTree(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} From b42b6c72eaba81d6a87900d08a5d06a1757bdab1 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 22 Dec 2024 09:56:56 +0100 Subject: [PATCH 20/59] refactoring and add tests --- ...FragmentControlFragmentControlPanelTool.cs | 23 + .../TestFragmentControlPanel.cs | 2 +- .../TestSectionFragmentControlPanelTool.cs | 11 + .../WebControl/UnitTestControlPanel.cs | 6 +- .../WebControl/UnitTestControlPanelFlexbox.cs | 2 +- .../WebControl/UnitTestControlPanelTool.cs | 128 +++++ .../WebFragment/UnitTestFragmentManager.cs | 1 + .../WebControl/ControlDropdown.cs | 532 +++++++++--------- .../WebControl/ControlPanel.cs | 43 +- .../WebControl/ControlPanelFlexbox.cs | 2 +- .../WebControl/ControlPanelTool.cs | 133 ++--- .../WebFragment/FragmentControlPanelTool.cs | 61 +- 12 files changed, 552 insertions(+), 392 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlFragmentControlPanelTool.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelTool.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlFragmentControlPanelTool.cs b/src/WebExpress.WebUI.Test/TestFragmentControlFragmentControlPanelTool.cs new file mode 100644 index 00000000..5c53c469 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlFragmentControlPanelTool.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlPanelTool : FragmentControlPanelTool + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlPanelTool(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Add(new ControlText() { Text = "TestFragmentControlPanelTool" }); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs index abc89e7a..d605dcaa 100644 --- a/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs +++ b/src/WebExpress.WebUI.Test/TestFragmentControlPanel.cs @@ -17,7 +17,7 @@ public sealed class TestFragmentControlPanel : FragmentControlPanel public TestFragmentControlPanel(IFragmentContext fragmentContext) : base(fragmentContext) { - AddChild(new ControlText() { Text = "TestFragmentControlPanel" }); + Add(new ControlText() { Text = "TestFragmentControlPanel" }); } } } diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelTool.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelTool.cs new file mode 100644 index 00000000..555ff63c --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlPanelTool.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlPanelTool : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs index 3c1d0024..0ee9a52d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -59,8 +59,8 @@ public void Direction(TypeDirection direction, string expected) /// Tests the fluid property of the panel control. /// [Theory] - [InlineData(TypePanelContainer.Default, @"
                                                                                                                                    ")] [InlineData(TypePanelContainer.None, @"
                                                                                                                                    ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                    ")] [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                    ")] public void Fluid(TypePanelContainer fluid, string expected) { @@ -85,7 +85,7 @@ public void Fluid(TypePanelContainer fluid, string expected) [InlineData(typeof(ControlText), @"
                                                                                                                                    ")] [InlineData(typeof(ControlLink), @"
                                                                                                                                    ")] [InlineData(typeof(ControlImage), @"
                                                                                                                                    ")] - public void AddChildren(Type child, string expected) + public void Add(Type child, string expected) { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); @@ -94,7 +94,7 @@ public void AddChildren(Type child, string expected) var control = new ControlPanel(); // test execution - control.AddChild(childInstance); + control.Add(childInstance); var html = control.Render(context); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs index fcd07659..9ee7e3e4 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs @@ -191,7 +191,7 @@ public void AddChildren(Type child, string expected) var control = new ControlPanelFlexbox(); // test execution - control.AddChild(childInstance); + control.Add(childInstance); var html = control.Render(context); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs new file mode 100644 index 00000000..9d524328 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs @@ -0,0 +1,128 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the tool panel control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelTool + { + /// + /// Tests the id property of the tool panel control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelTool(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the tool panel control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelTool() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the tool panel control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelTool() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tools property of the tool panel control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      *abc*
                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                      ")] + public void Tools(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = new ControlDropdownItemLink() { Text = text }; + var control = new ControlPanelTool() + { + }; + + // test execution + control.Tools.Add(childInstance); + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the tool panel control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                      **
                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                      **
                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelTool(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index 7481f00d..df9c368d 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -47,6 +47,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlNavigationItemLink), typeof(IScope), @"TestFragmentControlNavigationItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanel), typeof(IScope), @"
                                                                                                                                      TestFragmentControlPanel
                                                                                                                                      ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelFlexbox), typeof(IScope), @"
                                                                                                                                      ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelTool), typeof(IScope), @"
                                                                                                                                      *
                                                                                                                                      TestFragmentControlPanelTool
                                                                                                                                      ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlSplitButtonItemLink), typeof(IScope), @"TestFragmentControlSplitButtonItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlTree), typeof(IScope), @"
                                                                                                                                      ")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs index d668dd25..8ee985a0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs @@ -1,259 +1,273 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a dropdown control that can contain multiple items. - /// - public class ControlDropdown : Control, IControlNavigationItem - { - private readonly List _items = []; - - /// - /// Returns the items in the dropdown. - /// - public IEnumerable Items => _items; - - /// - /// Returns or sets the background color. - /// - public new PropertyColorButton BackgroundColor - { - get => (PropertyColorButton)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); - } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the outline property. - /// - public bool Outline { get; set; } - - /// - /// Returns or sets whether the button should take up the full width. - /// - public TypeBlockButton Block - { - get => (TypeBlockButton)GetProperty(TypeBlockButton.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets an indicator that indicates that a menu is present. - /// - public TypeToggleDropdown Toogle - { - get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the tooltip. - /// - public string Tooltip { get; set; } - - /// - /// Returns or sets the value. - /// - public string Value { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the activation status of the button. - /// - public TypeActive Active - { - get => (TypeActive)GetProperty(TypeActive.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the orientation of the menu. - /// - public TypeAlignmentDropdownMenu AlignmentMenu - { - get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the image. - /// - public string Image { get; set; } - - /// - /// Returns or sets the height. - /// - public new int Height { get; set; } = -1; - - /// - /// Returns or sets the width. - /// - public new int Width { get; set; } = -1; - - /// - /// Initializes a new instance of the class with the specified id and items. - /// - /// The id of the control. - /// The items to be added to the dropdown. - public ControlDropdown(string id = null, params IControlDropdownItem[] items) - : base(id) - { - _items.AddRange(items); - - Size = TypeSizeButton.Default; - } - /// - /// Adds one or more items to the dropdown. - /// - /// The item. - public void Add(params IControlDropdownItem[] items) - { - _items.AddRange(items); - } - - /// - /// Adds a new separator. - /// - public void AddSeperator() - { - _items.Add(null); - } - - /// - /// Adds a new head. - /// - /// The headline text. - public void AddHeader(string text) - { - _items.Add(new ControlDropdownItemHeader() { Text = text }); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) - { - var html = new HtmlElementTextContentDiv() - { - Id = Id, - Class = Css.Concatenate("dropdown", Margin.ToClass()), - Role = Role - }; - - if (Image == null) - { - var button = new HtmlElementFieldButton() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles(), - Title = I18N.Translate(Tooltip) - }; - button.AddUserAttribute("data-bs-toggle", "dropdown"); - button.AddUserAttribute("aria-expanded", "false"); - - if (Icon != null && Icon.HasIcon) - { - button.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - button.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); - } - - html.Add(button); - } - else - { - var button = new HtmlElementMultimediaImg() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles(), - Src = Image.ToString() - }; - button.AddUserAttribute("data-bs-toggle", "dropdown"); - button.AddUserAttribute("aria-expanded", "false"); - - if (Height > 0) - { - button.Height = Height; - } - - if (Width > 0) - { - button.Width = Width; - } - - html.Add(button); - } - - html.Add - ( - new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } - ).ToArray() - ) - { - Class = Css.Concatenate - ( - "dropdown-menu", - AlignmentMenu.ToClass() - ) - } - ); - - var modals = Items.Where(x => x is ControlDropdownItemLink) - .Select(x => x as ControlDropdownItemLink) - .Select(x => x.Modal) - .Where(x => x.Type == TypeModal.Modal) - .Select(x => x.Modal.Render(renderContext)); - - return new HtmlList(html, modals); - } - } -} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a dropdown control that can contain multiple items. + /// + public class ControlDropdown : Control, IControlNavigationItem + { + private readonly List _items = []; + + /// + /// Returns the items in the dropdown. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the background color. + /// + public new PropertyColorButton BackgroundColor + { + get => (PropertyColorButton)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); + } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the outline property. + /// + public bool Outline { get; set; } + + /// + /// Returns or sets whether the button should take up the full width. + /// + public TypeBlockButton Block + { + get => (TypeBlockButton)GetProperty(TypeBlockButton.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets an indicator that indicates that a menu is present. + /// + public TypeToggleDropdown Toogle + { + get => (TypeToggleDropdown)GetProperty(TypeToggleDropdown.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the tooltip. + /// + public string Tooltip { get; set; } + + /// + /// Returns or sets the value. + /// + public string Value { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the activation status of the button. + /// + public TypeActive Active + { + get => (TypeActive)GetProperty(TypeActive.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the orientation of the menu. + /// + public TypeAlignmentDropdownMenu AlignmentMenu + { + get => (TypeAlignmentDropdownMenu)GetProperty(TypeAlignmentDropdownMenu.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the image. + /// + public string Image { get; set; } + + /// + /// Returns or sets the height. + /// + public new int Height { get; set; } = -1; + + /// + /// Returns or sets the width. + /// + public new int Width { get; set; } = -1; + + /// + /// Initializes a new instance of the class with the specified id and items. + /// + /// The id of the control. + /// The items to be added to the dropdown. + public ControlDropdown(string id = null, params IControlDropdownItem[] items) + : base(id) + { + _items.AddRange(items); + + Size = TypeSizeButton.Default; + } + + /// + /// Adds one or more items to the dropdown. + /// + /// The items to add to the dropdown. + /// + /// This method allows adding one or multiple dropdown items to the collection of + /// the dropdown control. It is useful for dynamically constructing the dropdown menu by appending + /// various items to it. + /// Example usage: + /// + /// var dropdown = new DropdownControl(); + /// var item1 = new ControlDropdownItemLink { Text = "Option 1" }; + /// var item2 = new ControlDropdownItemLink { Text = "Option 2" }; + /// dropdown.Add(item1, item2); + /// + /// This method accepts any item that implements the interface. + /// + public void Add(params IControlDropdownItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds a new separator. + /// + public void AddSeperator() + { + _items.Add(null); + } + + /// + /// Adds a new head. + /// + /// The headline text. + public void AddHeader(string text) + { + _items.Add(new ControlDropdownItemHeader() { Text = text }); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("dropdown", Margin.ToClass()), + Role = Role + }; + + if (Image == null) + { + var button = new HtmlElementFieldButton() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles(), + Title = I18N.Translate(Tooltip) + }; + button.AddUserAttribute("data-bs-toggle", "dropdown"); + button.AddUserAttribute("aria-expanded", "false"); + + if (Icon != null && Icon.HasIcon) + { + button.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + button.Add(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))); + } + + html.Add(button); + } + else + { + var button = new HtmlElementMultimediaImg() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles(), + Src = Image.ToString() + }; + button.AddUserAttribute("data-bs-toggle", "dropdown"); + button.AddUserAttribute("aria-expanded", "false"); + + if (Height > 0) + { + button.Height = Height; + } + + if (Width > 0) + { + button.Width = Width; + } + + html.Add(button); + } + + html.Add + ( + new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } + ).ToArray() + ) + { + Class = Css.Concatenate + ( + "dropdown-menu", + AlignmentMenu.ToClass() + ) + } + ); + + var modals = Items.Where(x => x is ControlDropdownItemLink) + .Select(x => x as ControlDropdownItemLink) + .Select(x => x.Modal) + .Where(x => x.Type == TypeModal.Modal) + .Select(x => x.Modal.Render(renderContext)); + + return new HtmlList(html, modals); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 84814098..6407341d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -10,12 +10,16 @@ namespace WebExpress.WebUI.WebControl ///
                                                                                                                                      public class ControlPanel : Control { - private readonly List _children = []; + private readonly List _content = []; - // - // Returns the child controls contained within the control panel. - // - public IEnumerable Children => _children; + /// + /// Returns the content of the panel. + /// + /// + /// The content property holds a collection of controls that represent the visual and interactive elements + /// within this container. + /// + public IEnumerable Content => _content; /// /// Returns or sets the arrangement of the content. @@ -43,16 +47,29 @@ public TypePanelContainer Fluid public ControlPanel(string id = null, params IControl[] children) : base(id) { - _children.AddRange(children.Where(x => x != null)); + _content.AddRange(children.Where(x => x != null)); } - /// - /// Adds one or more child controls to the control panel. - /// - /// The child controls to add. - public void AddChild(params IControl[] children) + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var button1 = new ControlText { Text = "Save" }; + /// var button2 = new ControlText { Text = "Cancel" }; + /// panel.Add(button1, button2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] children) { - _children.AddRange(children); + _content.AddRange(children); } /// @@ -62,7 +79,7 @@ public void AddChild(params IControl[] children) /// An HTML node representing the rendered control. public override IHtmlNode Render(IRenderControlContext renderContext) { - return new HtmlElementTextContentDiv(Children.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs index e72a4d9d..3e882e2f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs @@ -70,7 +70,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Add(Children.Select(x => x.Render(renderContext))); + html.Add(Content.Select(x => x.Render(renderContext))); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs index 48d5858f..1b51c8e1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs @@ -1,85 +1,48 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Box with superimposed tools. -// /// -// public class ControlPanelTool : ControlPanel -// { -// /// -// /// Returns or sets the tools -// /// -// public ControlDropdown Tools { get; } = new ControlDropdown(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelTool(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelTool(string id, params Control[] items) -// : base(id, items) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelTool(params Control[] items) -// : base(items) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Border = new PropertyBorder(true); -// } - -// /// -// /// Adds controls to the panel. -// /// -// /// The controls to insert. -// public void Add(params Control[] items) -// { -// Content.AddRange(items); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var dropDown = Tools.Render(context); -// var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))); - -// var html = new HtmlElementTextContentDiv(dropDown, content) -// { -// Id = Id, -// Class = Css.Concatenate("toolpanel", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} +ο»Ώusing System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel tool that can contain multiple tools. + /// + public class ControlPanelTool : ControlPanel + { + /// + /// Returns the tools. + /// + public ControlDropdown Tools { get; } = new ControlDropdown(); + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlPanelTool(string id = null, params Control[] items) + : base(id, items) + { + Border = new PropertyBorder(true); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var dropDown = Tools.Render(renderContext); + var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()); + + var html = new HtmlElementTextContentDiv(dropDown, content) + { + Id = Id, + Class = Css.Concatenate("toolpanel", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs index f12e3068..1fdc867d 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlPanelTool.cs @@ -1,32 +1,35 @@ -ο»Ώ//using WebExpress.WebUI.WebControl; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlPanelTool : ControlPanelTool, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a control panel tool that is part of a fragment and implements the IFragmentControl interface. + /// + public class FragmentControlPanelTool : ControlPanelTool, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlPanelTool(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlPanelTool(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} From eae77335056933537c852d8cf21949f9e2a0fa76 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 22 Dec 2024 22:03:08 +0100 Subject: [PATCH 21/59] refactoring and add tests --- .../Fixture/AssertExtensions.cs | 4 +- .../IHtmlNodeExtensions.cs | 8 + .../WebControl/UnitTestControlButton.cs | 16 +- .../WebControl/UnitTestControlForm.cs | 151 ++- .../WebControl/UnitTestControlFormInline.cs | 1 + .../UnitTestControlFormItemButton.cs | 252 ++++ .../UnitTestControlFormItemButtonSubmit.cs | 252 ++++ ...estControlFormItemGroupColumnHorizontal.cs | 57 + .../UnitTestControlFormItemGroupColumnMix.cs | 57 + ...tTestControlFormItemGroupColumnVertical.cs | 57 + .../UnitTestControlFormItemGroupHorizontal.cs | 57 + .../UnitTestControlFormItemGroupMix.cs | 57 + .../UnitTestControlFormItemGroupVertical.cs | 57 + .../UnitTestControlFormItemHelpText.cs | 84 ++ .../UnitTestControlFormItemInputHidden.cs | 80 ++ .../UnitTestControlFormItemInputRadio.cs | 1 + .../UnitTestControlFormItemInputTextBox.cs | 269 ++++ .../UnitTestControlFormItemLabel.cs | 103 ++ .../WebControl/UnitTestControlModalForm.cs | 1 + .../WebControl/UnitTestControlProgressBar.cs | 235 ++++ .../WebControl/UnitTestControlText.cs | 4 +- .../WebControl/UnitTestControlTreeItem.cs | 1 + .../WebControl/ControlButton.cs | 59 +- .../WebControl/ControlButtonLink.cs | 4 +- .../WebControl/ControlDropdownItemLink.cs | 2 +- .../WebControl/ControlForm.cs | 1205 +++++++++-------- .../WebControl/ControlFormItem.cs | 102 +- .../WebControl/ControlFormItemButton.cs | 394 +++--- .../WebControl/ControlFormItemButtonSubmit.cs | 48 +- .../WebControl/ControlFormItemGroup.cs | 255 ++-- .../WebControl/ControlFormItemGroupColumn.cs | 251 ++-- .../ControlFormItemGroupColumnHorizontal.cs | 275 ++-- .../ControlFormItemGroupColumnMix.cs | 270 ++-- .../ControlFormItemGroupColumnVertical.cs | 260 ++-- .../ControlFormItemGroupHorizontal.cs | 228 ++-- .../WebControl/ControlFormItemGroupMix.cs | 230 ++-- .../ControlFormItemGroupVertical.cs | 188 ++- .../WebControl/ControlFormItemHelpText.cs | 117 +- .../WebControl/ControlFormItemInput.cs | 296 ++-- .../ControlFormItemInputCheckbox.cs | 4 +- .../WebControl/ControlFormItemInputHidden.cs | 94 +- .../WebControl/ControlFormItemInputTextBox.cs | 407 +++--- .../WebControl/ControlFormItemLabel.cs | 117 +- .../WebControl/ControlLink.cs | 61 +- .../WebControl/ControlList.cs | 238 ++-- .../WebControl/ControlPanel.cs | 216 +-- .../WebControl/ControlProgressBar.cs | 277 ++-- .../WebControl/FormEventArgs.cs | 40 +- .../WebControl/IControlForm.cs | 166 ++- .../WebControl/IFormValidation.cs | 51 +- .../WebControl/IRenderControlFormContext.cs | 21 + .../IRenderControlFormGroupContext.cs | 13 + .../WebControl/RenderContextForm.cs | 71 - .../WebControl/RenderContextFormGroup.cs | 34 - .../WebControl/RenderControlFormContext.cs | 58 + .../RenderControlFormGroupContext.cs | 24 + .../WebControl/ValidationEventArgs.cs | 48 +- .../WebControl/ValidationResult.cs | 54 +- .../WebControl/ValidationResultEventArgs.cs | 2 +- 59 files changed, 4903 insertions(+), 3081 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs create mode 100644 src/WebExpress.WebUI/WebControl/IRenderControlFormContext.cs create mode 100644 src/WebExpress.WebUI/WebControl/IRenderControlFormGroupContext.cs delete mode 100644 src/WebExpress.WebUI/WebControl/RenderContextForm.cs delete mode 100644 src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs create mode 100644 src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs create mode 100644 src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs diff --git a/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs index 1c21a1db..2bea175b 100644 --- a/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs +++ b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs @@ -23,7 +23,7 @@ public static partial class AssertExtensions /// The actual string to compare. public static void EqualWithPlaceholders(string expected, string actual) { - var str = RemoveLineBreaks(actual); + var str = RemoveLineBreaks(actual?.ToString() ?? "null"); Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); } @@ -35,7 +35,7 @@ public static void EqualWithPlaceholders(string expected, string actual) /// The actual string to compare. public static void EqualWithPlaceholders(string expected, IHtmlNode actual) { - var str = RemoveLineBreaks(actual.ToString()); + var str = RemoveLineBreaks(actual?.ToString() ?? "null"); Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); } diff --git a/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs index 6cff4fba..760b5704 100644 --- a/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs +++ b/src/WebExpress.WebUI.Test/IHtmlNodeExtensions.cs @@ -3,6 +3,9 @@ namespace WebExpress.WebUI.Test { + /// + /// Provides extension methods for the interface. + /// internal static class IHtmlNodeExtensions { /// @@ -12,6 +15,11 @@ internal static class IHtmlNodeExtensions /// A string with all consecutive spaces and line breaks reduced to single ones. public static string Trim(this IHtmlNode node) { + if (node == null) + { + return string.Empty; + } + var withoutExtraLineBreaks = Regex.Replace(node.ToString().Trim(), @"[\r\n]+", ""); var withoutExtraSpaces = Regex.Replace(withoutExtraLineBreaks, @"\s+", " "); var withoutSpacesBetweenBrackets = Regex.Replace(withoutExtraSpaces, @">\s+<", "><"); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs index 0c27db73..e764bd06 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -49,7 +49,7 @@ public void Text(string text, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -72,7 +72,7 @@ public void Size(TypeSizeButton size, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -98,7 +98,7 @@ public void BackgroundColor(TypeColorButton color, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -126,7 +126,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -148,7 +148,7 @@ public void Block(TypeBlockButton block, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -170,7 +170,7 @@ public void Icon(TypeIcon icon, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -192,7 +192,7 @@ public void Add() // test execution control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); - control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); var html1 = control1.Render(context); var html2 = control2.Render(context); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs index ca4c2bcc..5468e22f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs @@ -1,32 +1,132 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; -using Xunit.Abstractions; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.Test.WebControl { /// /// Tests the form control. /// - public class UnitTestControlForm : IClassFixture + [Collection("NonParallelTests")] + public class UnitTestControlForm { /// - /// Returns the log. + /// Tests the id property of the form control. /// - protected ITestOutputHelper Output { get; private set; } + [Theory] + [InlineData(null, @"*")] + [InlineData("id", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the backgroundcolor property of the form control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlForm() + { + BackgroundColor = new PropertyColorBackground(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } /// - /// Returns the test context. + /// Tests the form layout property of the form control. /// - protected UnitTestControlFixture Fixture { get; private set; } + [Theory] + [InlineData(TypeLayoutForm.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeLayoutForm.Inline, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void FormLayout(TypeLayoutForm formLayout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm() + { + FormLayout = formLayout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } /// - /// Initializes a new instance of the class. + /// Tests the item layout property of the form control. /// - /// The log. - /// The test context. - public UnitTestControlForm(UnitTestControlFixture fixture, ITestOutputHelper output) + [Theory] + [InlineData(TypeLayoutFormItem.Horizontal, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeLayoutFormItem.Vertical, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeLayoutFormItem.Mix, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void ItemLayout(TypeLayoutFormItem itemLayout, string expected) { - Fixture = fixture; - Output = output; + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm() + { + ItemLayout = itemLayout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -35,14 +135,15 @@ public UnitTestControlForm(UnitTestControlFixture fixture, ITestOutputHelper out [Fact] public void EmptyForm() { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlForm(); + // preconditions + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm(); - //var html = control.Render(context); + var html = control.Render(context); - //// test execution - //Assert.StartsWith("
                                                                                                                                      @@ -52,15 +153,15 @@ public void EmptyForm() public void EmptyFormChangeSubmitText() { // preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlForm(); - //control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlForm(); + control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); - //var html = control.Render(context); - //var str = html.ToString(); + var html = control.Render(context); - //// test execution - //Assert.Contains(@"sendbutton", html.Trim()); + // test execution + Assert.Contains(@"sendbutton", html.Trim()); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs index 5a67cb2a..2592df98 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs @@ -6,6 +6,7 @@ namespace WebExpress.WebUI.Test.WebControl /// /// Tests the inline form control. /// + [Collection("NonParallelTests")] public class UnitTestControlFormInline : IClassFixture { /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs new file mode 100644 index 00000000..2e969b8b --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs @@ -0,0 +1,252 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemButton + { + /// + /// Tests the id property of the form button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the form button control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the backgroundcolor property of the form button control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.White, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + BackgroundColor = new PropertyColorBackground(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the form button control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + [InlineData(TypeColorButton.Light, @"")] + public void Color(TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the form button control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + [InlineData(true, TypeColorButton.Light, @"")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Outline = outline, + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the block property of the form button control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the form button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButton() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the form button control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control1 = new ControlFormItemButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlFormItemButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlFormItemButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlFormItemButton(null); + var control5 = new ControlFormItemButton(null); + var control6 = new ControlFormItemButton(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + var html4 = control1.Render(context); + var html5 = control2.Render(context); + var html6 = control2.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html3.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html4.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html5.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs new file mode 100644 index 00000000..a4e69a28 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs @@ -0,0 +1,252 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form submit button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemButtonSubmit + { + /// + /// Tests the id property of the form submit button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form submit button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the form submit button control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the backgroundcolor property of the form submit button control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.White, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + BackgroundColor = new PropertyColorBackground(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the form submit button control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + [InlineData(TypeColorButton.Light, @"")] + public void Color(TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the form submit button control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + [InlineData(true, TypeColorButton.Light, @"")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Outline = outline, + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the block property of the form submit button control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the form submit button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemButtonSubmit() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the form submit button control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control1 = new ControlFormItemButtonSubmit(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlFormItemButtonSubmit(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlFormItemButtonSubmit(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlFormItemButtonSubmit(null); + var control5 = new ControlFormItemButtonSubmit(null); + var control6 = new ControlFormItemButtonSubmit(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + var html4 = control1.Render(context); + var html5 = control2.Render(context); + var html6 = control2.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html3.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html4.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html5.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs new file mode 100644 index 00000000..3ddb212c --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group column horizontal control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupColumnHorizontal + { + /// + /// Tests the id property of the form item group column horizontal control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnHorizontal(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group column horizontal control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnHorizontal() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs new file mode 100644 index 00000000..4aa11fff --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group column mix control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupColumnMix + { + /// + /// Tests the id property of the form item group column mix control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnMix(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group column mix control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnMix() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs new file mode 100644 index 00000000..303a50b0 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group column vertical control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupColumnVertical + { + /// + /// Tests the id property of the form item group column vertical control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnVertical(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group column vertical control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupColumnVertical() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs new file mode 100644 index 00000000..5b34df42 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group horizontal control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupHorizontal + { + /// + /// Tests the id property of the form item group horizontal control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupHorizontal(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group horizontal control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupHorizontal() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs new file mode 100644 index 00000000..5c3bd618 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group mix control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupMix + { + /// + /// Tests the id property of the form item group mix control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupMix(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group mix control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupMix() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs new file mode 100644 index 00000000..0f1be537 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs @@ -0,0 +1,57 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item group vertical control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemGroupVertical + { + /// + /// Tests the id property of the form item group vertical control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupVertical(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form item group vertical control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemGroupVertical() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs new file mode 100644 index 00000000..5e8ae299 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs @@ -0,0 +1,84 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item help text control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemHelpText + { + /// + /// Tests the id property of the form item help text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemHelpText(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form item help text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemHelpText() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the form item help text control. + /// + [Theory] + [InlineData(TypeSizeText.Default, @"")] + [InlineData(TypeSizeText.ExtraSmall, @"")] + [InlineData(TypeSizeText.Small, @"")] + [InlineData(TypeSizeText.Large, @"")] + [InlineData(TypeSizeText.ExtraLarge, @"")] + public void Size(TypeSizeText size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemHelpText() + { + Size = new PropertySizeText(size) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs new file mode 100644 index 00000000..025b6d57 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs @@ -0,0 +1,80 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form hidden control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputHidden + { + /// + /// Tests the id property of the form hidden control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputHidden(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form hidden control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputHidden() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form hidden control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputHidden() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs index 561f58a5..b8194625 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs @@ -6,6 +6,7 @@ namespace WebExpress.WebUI.Test.WebControl /// /// Tests the inline radio control. /// + [Collection("NonParallelTests")] public class UnitTestControlFormItemInputRadio : IClassFixture { /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs new file mode 100644 index 00000000..4a2997bb --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs @@ -0,0 +1,269 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form text control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputTextBox + { + /// + /// Tests the id property of the form label control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the format property of the form text control. + /// + [Theory] + [InlineData(TypesEditTextFormat.Default, @"")] + [InlineData(TypesEditTextFormat.Multiline, @"")] + [InlineData(TypesEditTextFormat.Wysiwyg, @"")] + public void Format(TypesEditTextFormat format, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Format = format + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the description property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Description(string description, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Description = description + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the placeholder property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Placeholder(string placeholder, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Placeholder = placeholder + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the min length property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData(0u, @"")] + [InlineData(10u, @"")] + public void MinLength(uint? minLength, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + MinLength = minLength + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the max length property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData(0u, @"")] + [InlineData(10u, @"")] + public void MaxLength(uint? maxLength, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + MaxLength = maxLength + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the required property of the form text control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void Required(bool required, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Required = required + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the pattern property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc.*", @"")] + public void Pattern(string pattern, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Pattern = pattern + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the rows property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData(0u, @"")] + [InlineData(10u, @"")] + public void Rows(uint? rows, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Rows = rows, + Format = TypesEditTextFormat.Multiline + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form text control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputTextBox() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs new file mode 100644 index 00000000..765946b1 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs @@ -0,0 +1,103 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form label control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemLabel + { + /// + /// Tests the id property of the form label control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemLabel(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form label control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemLabel() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form label control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemLabel() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the form item property of the form label control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void FormItem(bool formItem, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemLabel() + { + FormItem = formItem ? new ControlFormItemInputTextBox() : null + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs index c660860b..2511cf7f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs @@ -6,6 +6,7 @@ namespace WebExpress.WebUI.Test.WebControl /// /// Tests the modal form control. /// + [Collection("NonParallelTests")] public class UnitTestControlModalForm : IClassFixture { /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs new file mode 100644 index 00000000..9c30a3d1 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs @@ -0,0 +1,235 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the progress bar control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlProgressBar + { + /// + /// Tests the id property of the progress bar control. + /// + [Theory] + [InlineData(null, @"0%")] + [InlineData("id", @"0%")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the format property of the progress bar control. + /// + [Theory] + [InlineData(TypeFormatProgress.Default, @"0%")] + [InlineData(TypeFormatProgress.Colored, @"
                                                                                                                                      ")] + [InlineData(TypeFormatProgress.Striped, @"
                                                                                                                                      ")] + [InlineData(TypeFormatProgress.Animated, @"
                                                                                                                                      ")] + public void Format(TypeFormatProgress format, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar() + { + Format = format + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the progress bar control. + /// + [Theory] + [InlineData(TypeSizeProgress.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeSizeProgress.ExtraSmall, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeSizeProgress.Small, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeSizeProgress.Large, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeSizeProgress.ExtraLarge, @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Size(TypeSizeProgress size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar() + { + Size = size, + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the progress bar control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                      WebExpress.WebUI
                                                                                                                                      ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar() + { + Text = text, + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the color property of the progress bar control. + /// + [Theory] + [InlineData(TypeColorProgress.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorProgress.Primary, @"
                                                                                                                                      <* class=""progress-bar bg-primary"" */div>")] + [InlineData(TypeColorProgress.Secondary, @"
                                                                                                                                      <* class=""progress-bar bg-secondary"" */div>")] + [InlineData(TypeColorProgress.Info, @"
                                                                                                                                      <* class=""progress-bar bg-info"" */div>")] + [InlineData(TypeColorProgress.Warning, @"
                                                                                                                                      <* class=""progress-bar bg-warning"" */div>")] + [InlineData(TypeColorProgress.Danger, @"
                                                                                                                                      <* class=""progress-bar bg-danger"" */div>")] + [InlineData(TypeColorProgress.Light, @"
                                                                                                                                      <* class=""progress-bar bg-light"" */div>")] + [InlineData(TypeColorProgress.White, @"
                                                                                                                                      <* class=""progress-bar bg-white"" */div>")] + public void Color(TypeColorProgress color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar() + { + Color = new PropertyColorProgress(color), + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the progress bar control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                      <* class=""progress-bar text-primary"" */div>")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                      <* class=""progress-bar text-secondary"" */div>")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                      <* class=""progress-bar text-info"" */div>")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                      <* class=""progress-bar text-warning"" */div>")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                      <* class=""progress-bar text-danger"" */div>")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                      <* class=""progress-bar text-light"" */div>")] + [InlineData(TypeColorText.White, @"
                                                                                                                                      <* class=""progress-bar text-white"" */div>")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                      <* class=""progress-bar text-muted"" */div>")] + public void TextColor(TypeColorText textColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlProgressBar() + { + TextColor = new PropertyColorText(textColor), + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the min property of the form progress bar control. + /// + [Theory] + [InlineData(0u, @"0%")] + [InlineData(100u, @"0%")] + public void Min(uint min, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlProgressBar() + { + Min = min + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the max property of the form progress bar control. + /// + [Theory] + [InlineData(0u, @"0%")] + [InlineData(100u, @"0%")] + public void Max(uint max, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlProgressBar() + { + Max = max + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form progress bar control. + /// + [Theory] + [InlineData(0, @"0%")] + [InlineData(100, @"100%")] + public void Value(int value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlProgressBar() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs index 3c1e1893..a939af9d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -52,7 +52,7 @@ public void Text(string text, TypeFormatText format, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs index cd941f1b..9553112b 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs @@ -6,6 +6,7 @@ namespace WebExpress.WebUI.Test.WebControl /// /// Tests the tree item control. /// + [Collection("NonParallelTests")] public class UnitTestControlTreeItem : IClassFixture { /// diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index 2c7a4b6b..22f79aca 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -11,7 +11,15 @@ namespace WebExpress.WebUI.WebControl /// public class ControlButton : Control, IControlButton { - private readonly List _children = []; + private readonly List _content = []; + + /// + /// Returns the content of the control. + /// + /// + /// An enumerable collection of child controls. + /// + public IEnumerable Content => _content; /// /// Returns or sets the color. @@ -45,11 +53,6 @@ public TypeBlockButton Block set => SetProperty(value, () => value.ToClass()); } - /// - /// Returns the children. - /// - public IEnumerable Children => _children; - /// /// Returns or sets the text. /// @@ -88,25 +91,51 @@ public ControlButton(string id = null, params IControl[] content) : base(id) { Size = TypeSizeButton.Default; - _children.AddRange(content); + _content.AddRange(content); } /// - /// Adds one or more content. + /// Adds one or more controls to the content. /// - /// The content to add to the button. + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var button = new ControlButton(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// button.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// public void Add(params IControl[] items) { - _children.AddRange(items); + _content.AddRange(items); } /// - /// Adds one or more items to the split button. + /// Adds one or more controls to the content. /// - /// The items to add to the split button. + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var button = new ControlButton(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// button.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// public void Add(IEnumerable items) { - _children.AddRange(items); + _content.AddRange(items); } /// @@ -153,9 +182,9 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("onclick", OnClick?.ToString()); } - if (_children.Count != 0) + if (_content.Count != 0) { - html.Add(_children.Select(x => x.Render(renderContext)).ToArray()); + html.Add(_content.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index 94c1a951..aac4c497 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -72,9 +72,9 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.Add(new HtmlText(text)); } - if (Children.Any()) + if (Content.Any()) { - html.Add(Children.Select(x => x.Render(renderContext)).ToArray()); + html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index 91a5b226..2c25e717 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -29,7 +29,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) { var param = ""; // GetParams(context?.Page); - var html = new HtmlElementTextSemanticsA(Children.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(Controls.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index cef87263..d7c14087 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -1,601 +1,604 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebFragment; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebMessage; -//using WebExpress.WebCore.WebPage; -//using WebExpress.WebCore.WebScope; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Represents a form with various input fields and controls. -// /// -// public class ControlForm : Control, IControlForm, IScope -// { -// private readonly List _items = []; -// private readonly List _preferencesButtons = []; -// private readonly List _primaryButtons = []; -// private readonly List _secondaryButtons = []; -// private readonly List _preferencesControls = []; -// private readonly List _primaryControls = []; -// private readonly List _secondaryControls = []; - -// /// -// /// Event to validate the input values. -// /// -// public event EventHandler Validation; - -// /// -// /// Event nach Abschluss der Validation -// /// -// public event EventHandler Validated; - -// /// -// /// Event is raised when the form has been initialized. -// /// -// public event EventHandler InitializeForm; - -// /// -// /// Event is raised when the form's data needs to be determined. -// /// -// public event EventHandler FillForm; - -// /// -// /// Event is raised when the form is about to be processed. -// /// -// public event EventHandler ProcessForm; - -// /// -// /// Event is raised when the form is to be processed and the next data is to be loaded. -// /// -// public event EventHandler ProcessAndNextForm; - -// /// -// /// Returns or sets the name of the form. -// /// -// public string Name { get; set; } - -// /// -// /// Returns or sets the target uri. -// /// -// public string Uri { get; set; } - -// /// -// /// Returns or sets the redirect uri. -// /// -// public string RedirectUri { get; set; } - -// /// -// /// Returns or sets the form layout. -// /// -// public virtual TypeLayoutForm FormLayout { get; set; } = TypeLayoutForm.Default; - -// /// -// /// Returns or sets the item layout. -// /// -// public virtual TypeLayoutFormItem ItemLayout { get; set; } = TypeLayoutFormItem.Vertical; - -// /// -// /// Returns or sets the hidden field that contains the id. -// /// -// public ControlFormItemInputHidden FormId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) -// { -// Name = "form-id" -// }; - -// /// -// /// Returns or sets the hidden field that contains the submit method. -// /// -// public ControlFormItemInputHidden SubmitType { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) -// { -// Name = "form-submit-type", -// Value = "update" -// }; - -// /// -// /// Returns or sets the request method. -// /// -// public RequestMethod Method { get; set; } = RequestMethod.POST; - -// /// -// /// Returns or sets the header preferences section. -// /// -// protected List HeaderPreferences { get; } = []; - -// /// -// /// Returns or sets the header primary section. -// /// -// protected List HeaderPrimary { get; } = []; - -// /// -// /// Returns or sets the header secondary section. -// /// -// protected List HeaderSecondary { get; } = []; - -// /// -// /// Returns or sets the button panel preferences section. -// /// -// protected List ButtonPanelPreferences { get; } = []; - -// /// -// /// Returns or sets the button panel primary section. -// /// -// protected List ButtonPanelPrimary { get; } = []; - -// /// -// /// Returns or sets the button panel secondary section. -// /// -// protected List ButtonPanelSecondary { get; } = []; - -// /// -// /// Returns or sets the footer preferences section. -// /// -// protected List FooterPreferences { get; } = []; - -// /// -// /// Returns or sets the footer primary section. -// /// -// protected List FooterPrimary { get; } = []; - -// /// -// /// Returns or sets the footer secondary section. -// /// -// protected List FooterSecondary { get; } = []; - -// /// -// /// Returns the form items. -// /// -// public IEnumerable Items => _items; - -// /// -// /// Returns the form buttons. -// /// -// public IEnumerable Buttons => _preferencesButtons.Union(_primaryButtons).Union(_secondaryButtons); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlForm(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The controls that are associated with the form. -// public ControlForm(string id, params ControlFormItem[] items) -// : this(id) -// { -// _items.AddRange(items); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The controls that are associated with the form. -// public ControlForm(params ControlFormItem[] items) -// : this(null, items) -// { -// } - -// /// -// /// Initializes the form. -// /// -// /// The context in which the control is rendered. -// public virtual void Initialize(RenderContextForm context) -// { -// //var fm = ComponentHub.GetComponent(); - -// //// check id -// //if (string.IsNullOrWhiteSpace(Id)) -// //{ -// // context.ApplicationContext?.PluginContext.Host.Log.Warning(I18N.Translate("webexpress.webui:form.empty.id")); -// //} - -// //FormId.Value = Id; - -// //// header -// //HeaderPreferences.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPreferences, context.Page, [GetType().FullName])); -// //HeaderPrimary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPrimary, context.Page, [GetType().FullName])); -// //HeaderSecondary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderSecondary, context.Page, [GetType().FullName])); - -// //// footer -// //FooterPreferences.AddRange(fm.GetCacheableFragments(SectionControl.FooterPreferences, context.Page, [GetType().FullName])); -// //FooterPrimary.AddRange(fm.GetCacheableFragments(SectionControl.FooterPrimary, context.Page, [GetType().FullName])); -// //FooterSecondary.AddRange(fm.GetCacheableFragments(SectionControl.FooterSecondary, context.Page, [GetType().FullName])); -// } - -// /// -// /// Filling the form. -// /// -// /// The context in which the control is rendered. -// public virtual void Fill(RenderContextForm context) -// { -// OnFill(context); -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// /// True if all form items are valid, false otherwise. -// public virtual bool Validate(RenderContextForm context) -// { -// var valid = true; -// var validationResults = context.ValidationResults as List; - -// foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) -// { -// v.Validate(context); - -// if (v.ValidationResult == TypesInputValidity.Error) -// { -// valid = false; -// } - -// validationResults.AddRange(v.ValidationResults); -// } - -// var args = new ValidationEventArgs() { Value = null, Context = context }; -// OnValidation(args); - -// validationResults.AddRange(args.Results); - -// if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) -// { -// valid = false; -// } - -// var validatedArgs = new ValidationResultEventArgs(valid); -// validatedArgs.Results.AddRange(validationResults); - -// OnValidated(validatedArgs); - -// return valid; -// } - -// /// -// /// Instructs to reload the initial form data. -// /// -// public void Reset() -// { -// Fill(null); -// } - -// /// -// /// Pre-processing of the form. -// /// -// /// The context in which the control is rendered. -// public virtual void PreProcess(RenderContextForm context) -// { - -// } - -// /// -// /// Processing of the form. -// /// -// /// The context in which the control is rendered. -// public virtual void Process(RenderContextForm context) -// { -// //OnProcess(context); - -// //if (!string.IsNullOrWhiteSpace(RedirectUri?.ToString())) -// //{ -// // context.Page.Redirecting(RedirectUri); -// //} -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return Render(context, Items); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The form items. -// /// The control as html. -// public virtual IHtmlNode Render(IRenderContext context, IEnumerable items) -// { -// var renderContext = new RenderContextForm(context, this); -// var fill = false; -// var process = false; - -// // check if and how the form was submitted -// if (context.Request.GetParameter("form-id")?.Value == Id && context.Request.HasParameter("form-submit-type")) -// { -// var value = context.Request.GetParameter("form-submit-type")?.Value; -// switch (value) -// { -// case "submit": -// process = true; -// fill = false; -// break; -// case "reset": -// process = false; -// fill = true; -// break; -// case "update": -// default: -// break; -// } -// } -// else -// { -// // first call -// fill = true; -// process = false; -// } - -// // initialization -// Initialize(renderContext); -// foreach (var item in items) -// { -// item.Initialize(renderContext); -// } -// foreach (var item in Buttons) -// { -// item.Initialize(renderContext); -// } -// OnInitialize(renderContext); - -// // fill the form with data -// if (fill) -// { -// Fill(renderContext); -// } - -// // preprocessing -// PreProcess(renderContext); - -// // process form (e.g. save form data) -// if (process && Validate(renderContext)) -// { -// Process(renderContext); -// } - -// // generate html -// var form = new HtmlElementFormForm() -// { -// Id = Id, -// Class = FormLayout == TypeLayoutForm.Inline ? Css.Concatenate("form-inline", GetClasses()) : GetClasses(), -// Style = GetStyles(), -// Role = Role, -// Action = Uri?.ToString() ?? renderContext.Uri?.ToString(), -// Method = Method.ToString(), -// Enctype = TypeEnctype.None -// }; - -// form.Elements.Add(FormId.Render(renderContext)); -// form.Elements.Add(SubmitType.Render(renderContext)); -// var header = new HtmlElementSectionHeader(); -// header.Elements.Add(new ControlProgressBar() -// { -// Format = TypeFormatProgress.Animated, -// Color = new PropertyColorProgress(TypeColorProgress.Success), -// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three), -// Styles = { "height: 3px;", "display: none;" }, -// Value = 0 -// }.Render(renderContext)); - -// //header.Elements.AddRange(HeaderPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); -// //header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); -// //header.Elements.AddRange(HeaderSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - -// foreach (var v in renderContext.ValidationResults) -// { -// var bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Default); - -// switch (v.Type) -// { -// case TypesInputValidity.Error: -// bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Danger); -// break; -// case TypesInputValidity.Warning: -// bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Warning); -// break; -// } - -// header.Elements.Add(new ControlAlert() -// { -// BackgroundColor = bgColor, -// Text = I18N.Translate(v.Text), -// Dismissible = TypeDismissibleAlert.Dismissible, -// Fade = TypeFade.FadeShow -// }.Render(renderContext)); -// } - -// foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) -// { -// form.Elements.Add(item.Render(renderContext)); -// } - -// var main = new HtmlElementSectionMain(); - -// var group = default(ControlFormItemGroup); - -// group = ItemLayout switch -// { -// TypeLayoutFormItem.Horizontal => new ControlFormItemGroupHorizontal(), -// TypeLayoutFormItem.Mix => new ControlFormItemGroupMix(), -// _ => new ControlFormItemGroupVertical(), -// }; - -// foreach (var item in items.Where(x => x is not ControlFormItemInputHidden)) -// { -// group.Items.Add(item); -// } - -// main.Elements.Add(group.Render(renderContext)); - -// var buttonPannel = new HtmlElementTextContentDiv(); -// buttonPannel.Elements.AddRange(Buttons.Select(x => x.Render(renderContext))); - -// var footer = new HtmlElementSectionFooter(); -// //footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - -// //footer.Elements.AddRange(FooterPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); -// //footer.Elements.AddRange(FooterSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); - -// form.Elements.Add(header); -// form.Elements.Add(main); -// form.Elements.Add(buttonPannel); -// form.Elements.Add(footer); - -// form.Elements.AddRange(renderContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); - -// context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{Method.ToString()}');"); - -// return form; -// } - -// /// -// /// Adds a form control. -// /// -// /// The form item. -// public void Add(params ControlFormItem[] item) -// { -// _items.AddRange(item); -// } - -// /// -// /// Adds a preferences control. -// /// -// /// The controls. -// public void AddPreferencesControl(params ControlFormItem[] controls) -// { -// _preferencesControls.AddRange(controls); -// } - -// /// -// /// Adds a preferences form control button. -// /// -// /// The form buttons. -// public void AddPreferencesButton(params ControlFormItemButton[] buttons) -// { -// _preferencesButtons.AddRange(buttons); -// } - -// /// -// /// Adds a primary control. -// /// -// /// The controls. -// public void AddPrimaryControl(params ControlFormItem[] controls) -// { -// _primaryControls.AddRange(controls); -// } - -// /// -// /// Adds a primary form control button. -// /// -// /// The form buttons. -// public void AddPrimaryButton(params ControlFormItemButton[] buttons) -// { -// _primaryButtons.AddRange(buttons); -// } - -// /// -// /// Adds a secondary control. -// /// -// /// The controls. -// public void AddSecondaryControl(params ControlFormItem[] controls) -// { -// _secondaryControls.AddRange(controls); -// } - -// /// -// /// Adds a secondary form control button. -// /// -// /// The form buttons. -// public void AddSecondaryButton(params ControlFormItemButton[] buttons) -// { -// _secondaryButtons.AddRange(buttons); -// } - -// /// -// /// Removes a form control item from the form. -// /// -// /// The form item. -// public void Remove(ControlFormItem formItem) -// { -// _items.Remove(formItem); -// } - -// /// -// /// Removes a form control button from the form. -// /// -// /// The form button. -// public void RemoveButton(ControlFormItemButton button) -// { -// _preferencesButtons.Remove(button); -// _primaryButtons.Remove(button); -// _secondaryButtons.Remove(button); -// } - -// /// -// /// Raises the process event. -// /// -// /// The context in which the control is rendered. -// protected virtual void OnProcess(RenderContextForm context) -// { -// ProcessForm?.Invoke(this, new FormEventArgs() { Context = context }); -// } - -// /// -// /// Raises the process event. -// /// -// /// The context in which the control is rendered. -// protected virtual void OnProcessAndNextForm(RenderContextForm context) -// { -// ProcessAndNextForm?.Invoke(this, new FormEventArgs() { Context = context }); -// } - -// /// -// /// Raises the Initializations event. -// /// -// /// The context in which the control is rendered. -// protected virtual void OnInitialize(RenderContextForm context) -// { -// InitializeForm?.Invoke(this, new FormEventArgs() { Context = context }); -// } - -// /// -// /// Raises the data delivery event. -// /// -// /// The context in which the control is rendered. -// protected virtual void OnFill(RenderContextForm context) -// { -// FillForm?.Invoke(this, new FormEventArgs() { Context = context }); -// } - -// /// -// /// Raises the validation event. -// /// -// /// The event argument. -// protected virtual void OnValidation(ValidationEventArgs e) -// { -// Validation?.Invoke(this, e); -// } - -// /// -// /// Raises the Validated event. -// /// -// /// The event argument. -// protected virtual void OnValidated(ValidationResultEventArgs e) -// { -// Validated?.Invoke(this, e); -// } -// } -//} +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebPage; +using WebExpress.WebCore.WebScope; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form with various input fields and controls. + /// + public class ControlForm : Control, IControlForm, IScope + { + private readonly List _items = []; + private readonly List _preferencesButtons = []; + private readonly List _primaryButtons = []; + private readonly List _secondaryButtons = []; + private readonly List _preferencesControls = []; + private readonly List _primaryControls = []; + private readonly List _secondaryControls = []; + + /// + /// Event to validate the input values. + /// + public event EventHandler Validation; + + /// + /// Event nach Abschluss der Validation + /// + public event EventHandler Validated; + + /// + /// Event is raised when the form has been initialized. + /// + public event EventHandler InitializeForm; + + /// + /// Event is raised when the form's data needs to be determined. + /// + public event EventHandler FillForm; + + /// + /// Event is raised when the form is about to be processed. + /// + public event EventHandler ProcessForm; + + /// + /// Event is raised when the form is to be processed and the next data is to be loaded. + /// + public event EventHandler ProcessAndNextForm; + + /// + /// Returns the form items. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the name of the form. + /// + public string Name { get; set; } + + /// + /// Returns or sets the target uri. + /// + public string Uri { get; set; } + + /// + /// Returns or sets the redirect uri. + /// + public string RedirectUri { get; set; } + + /// + /// Returns or sets the form layout. + /// + public virtual TypeLayoutForm FormLayout { get; set; } = TypeLayoutForm.Default; + + /// + /// Returns or sets the item layout. + /// + public virtual TypeLayoutFormItem ItemLayout { get; set; } = TypeLayoutFormItem.Vertical; + + /// + /// Returns or sets the hidden field that contains the id. + /// + public ControlFormItemInputHidden FormId { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) + { + Name = "form-id" + }; + + /// + /// Returns or sets the hidden field that contains the submit method. + /// + public ControlFormItemInputHidden SubmitType { get; } = new ControlFormItemInputHidden(Guid.NewGuid().ToString()) + { + Name = "form-submit-type", + Value = "update" + }; + + /// + /// Returns or sets the request method. + /// + public RequestMethod Method { get; set; } = RequestMethod.POST; + + /// + /// Returns or sets the header preferences section. + /// + protected List HeaderPreferences { get; } = []; + + /// + /// Returns or sets the header primary section. + /// + protected List HeaderPrimary { get; } = []; + + /// + /// Returns or sets the header secondary section. + /// + protected List HeaderSecondary { get; } = []; + + /// + /// Returns or sets the button panel preferences section. + /// + protected List ButtonPanelPreferences { get; } = []; + + /// + /// Returns or sets the button panel primary section. + /// + protected List ButtonPanelPrimary { get; } = []; + + /// + /// Returns or sets the button panel secondary section. + /// + protected List ButtonPanelSecondary { get; } = []; + + /// + /// Returns or sets the footer preferences section. + /// + protected List FooterPreferences { get; } = []; + + /// + /// Returns or sets the footer primary section. + /// + protected List FooterPrimary { get; } = []; + + /// + /// Returns or sets the footer secondary section. + /// + protected List FooterSecondary { get; } = []; + + /// + /// Returns the form buttons. + /// + public IEnumerable Buttons => _preferencesButtons.Union(_primaryButtons).Union(_secondaryButtons); + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlForm(string id = null) + : base(id) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The controls that are associated with the form. + public ControlForm(string id, params ControlFormItem[] items) + : this(id) + { + _items.AddRange(items); + } + + /// + /// Initializes a new instance of the class. + /// + /// The controls that are associated with the form. + public ControlForm(params ControlFormItem[] items) + : this(null, items) + { + } + + /// + /// Initializes the form. + /// + /// The context in which the control is rendered. + public virtual void Initialize(RenderControlFormContext context) + { + var fm = WebEx.ComponentHub.FragmentManager; + + // check id + if (string.IsNullOrWhiteSpace(Id)) + { + //context.ApplicationContext?.PluginContext.Host.Log.Warning(I18N.Translate("webexpress.webui:form.empty.id")); + } + + FormId.Value = Id; + + // header + //HeaderPreferences.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPreferences, context.Page, [GetType().FullName])); + //HeaderPrimary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderPrimary, context.Page, [GetType().FullName])); + //HeaderSecondary.AddRange(fm.GetCacheableFragments(SectionControl.HeaderSecondary, context.Page, [GetType().FullName])); + + //// footer + //FooterPreferences.AddRange(fm.GetCacheableFragments(SectionControl.FooterPreferences, context.Page, [GetType().FullName])); + //FooterPrimary.AddRange(fm.GetCacheableFragments(SectionControl.FooterPrimary, context.Page, [GetType().FullName])); + //FooterSecondary.AddRange(fm.GetCacheableFragments(SectionControl.FooterSecondary, context.Page, [GetType().FullName])); + } + + /// + /// Filling the form. + /// + /// The context in which the control is rendered. + public virtual void Fill(IRenderControlFormContext renderContext) + { + OnFill(renderContext); + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + /// True if all form items are valid, false otherwise. + public virtual bool Validate(IRenderControlFormContext renderContext) + { + var valid = true; + var validationResults = renderContext.ValidationResults as List; + + foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) + { + v.Validate(renderContext); + + if (v.ValidationResult == TypesInputValidity.Error) + { + valid = false; + } + + validationResults.AddRange(v.ValidationResults); + } + + var args = new ValidationEventArgs() { Value = null, Context = renderContext }; + OnValidation(args); + + validationResults.AddRange(args.Results); + + if (args.Results.Where(x => x.Type == TypesInputValidity.Error).Any()) + { + valid = false; + } + + var validatedArgs = new ValidationResultEventArgs(valid); + validatedArgs.Results.AddRange(validationResults); + + OnValidated(validatedArgs); + + return valid; + } + + /// + /// Instructs to reload the initial form data. + /// + public void Reset() + { + Fill(null); + } + + /// + /// Pre-processing of the form. + /// + /// The context in which the control is rendered. + public virtual void PreProcess(IRenderControlFormContext renderContext) + { + + } + + /// + /// Processing of the form. + /// + /// The context in which the control is rendered. + public virtual void Process(IRenderControlFormContext renderContext) + { + OnProcess(renderContext); + + if (!string.IsNullOrWhiteSpace(RedirectUri?.ToString())) + { + throw new RedirectException(RedirectUri); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return Render(renderContext, Items); + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The form items. + /// The control as html. + public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + { + var renderFormContext = new RenderControlFormContext(renderContext, this); + var fill = false; + var process = false; + + // check if and how the form was submitted + if (renderContext.Request.GetParameter("form-id")?.Value == Id && renderContext.Request.HasParameter("form-submit-type")) + { + var value = renderContext.Request.GetParameter("form-submit-type")?.Value; + switch (value) + { + case "submit": + process = true; + fill = false; + break; + case "reset": + process = false; + fill = true; + break; + case "update": + default: + break; + } + } + else + { + // first call + fill = true; + process = false; + } + + // initialization + Initialize(renderFormContext); + + foreach (var item in items) + { + item.Initialize(renderFormContext); + } + foreach (var item in Buttons) + { + item.Initialize(renderFormContext); + } + + OnInitialize(renderFormContext); + + // fill the form with data + if (fill) + { + Fill(renderFormContext); + } + + // preprocessing + PreProcess(renderFormContext); + + // process form (e.g. save form data) + if (process && Validate(renderFormContext)) + { + Process(renderFormContext); + } + + // generate html + var form = new HtmlElementFormForm() + { + Id = Id, + Class = FormLayout == TypeLayoutForm.Inline ? Css.Concatenate("form-inline", GetClasses()) : GetClasses(), + Style = GetStyles(), + Role = Role, + Action = Uri?.ToString() ?? renderFormContext.Uri?.ToString(), + Method = Method.ToString(), + Enctype = TypeEnctype.None + }; + + form.Add(FormId.Render(renderFormContext)); + form.Add(SubmitType.Render(renderFormContext)); + + var header = new HtmlElementSectionHeader(); + header.Add(new ControlProgressBar() + { + Format = TypeFormatProgress.Animated, + Color = new PropertyColorProgress(TypeColorProgress.Success), + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three), + Styles = { "height: 3px;", "display: none;" }, + Value = 0 + }.Render(renderFormContext)); + + //header.Elements.AddRange(HeaderPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + //header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + //header.Elements.AddRange(HeaderSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + + foreach (var v in renderFormContext.ValidationResults) + { + var bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Default); + + switch (v.Type) + { + case TypesInputValidity.Error: + bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Danger); + break; + case TypesInputValidity.Warning: + bgColor = new PropertyColorBackgroundAlert(TypeColorBackground.Warning); + break; + } + + header.Add(new ControlAlert() + { + BackgroundColor = bgColor, + Text = I18N.Translate(renderContext.Request?.Culture, v.Text), + Dismissible = TypeDismissibleAlert.Dismissible, + Fade = TypeFade.FadeShow + }.Render(renderFormContext)); + } + + foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) + { + form.Add(item.Render(renderFormContext)); + } + + var main = new HtmlElementSectionMain(); + + var group = default(ControlFormItemGroup); + + group = ItemLayout switch + { + TypeLayoutFormItem.Horizontal => new ControlFormItemGroupHorizontal(), + TypeLayoutFormItem.Mix => new ControlFormItemGroupMix(), + _ => new ControlFormItemGroupVertical(), + }; + + foreach (var item in items.Where(x => x is not ControlFormItemInputHidden)) + { + group.Items.Add(item); + } + + main.Add(group.Render(renderFormContext)); + + var buttonPannel = new HtmlElementTextContentDiv(); + buttonPannel.Add(Buttons.Select(x => x.Render(renderFormContext))); + + var footer = new HtmlElementSectionFooter(); + //footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + //footer.Elements.AddRange(FooterPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + //footer.Elements.AddRange(FooterSecondary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); + + form.Add(header); + form.Add(main); + form.Add(buttonPannel); + form.Add(footer); + + //form.Add(renderFormContext.Scripts.Select(x => new HtmlElementScriptingScript(x.Value))); + //context.VisualTree.AddScript(Id, $"new webexpress.webui.form.progess('{Id}', '{Method.ToString()}');"); + + return form; + } + + /// + /// Adds a form control. + /// + /// The form item. + public void Add(params ControlFormItem[] item) + { + _items.AddRange(item); + } + + /// + /// Adds a preferences control. + /// + /// The controls. + public void AddPreferencesControl(params ControlFormItem[] controls) + { + _preferencesControls.AddRange(controls); + } + + /// + /// Adds a preferences form control button. + /// + /// The form buttons. + public void AddPreferencesButton(params ControlFormItemButton[] buttons) + { + _preferencesButtons.AddRange(buttons); + } + + /// + /// Adds a primary control. + /// + /// The controls. + public void AddPrimaryControl(params ControlFormItem[] controls) + { + _primaryControls.AddRange(controls); + } + + /// + /// Adds a primary form control button. + /// + /// The form buttons. + public void AddPrimaryButton(params ControlFormItemButton[] buttons) + { + _primaryButtons.AddRange(buttons); + } + + /// + /// Adds a secondary control. + /// + /// The controls. + public void AddSecondaryControl(params ControlFormItem[] controls) + { + _secondaryControls.AddRange(controls); + } + + /// + /// Adds a secondary form control button. + /// + /// The form buttons. + public void AddSecondaryButton(params ControlFormItemButton[] buttons) + { + _secondaryButtons.AddRange(buttons); + } + + /// + /// Removes a form control item from the form. + /// + /// The form item. + public void Remove(ControlFormItem formItem) + { + _items.Remove(formItem); + } + + /// + /// Removes a form control button from the form. + /// + /// The form button. + public void RemoveButton(ControlFormItemButton button) + { + _preferencesButtons.Remove(button); + _primaryButtons.Remove(button); + _secondaryButtons.Remove(button); + } + + /// + /// Raises the process event. + /// + /// The context in which the control is rendered. + protected virtual void OnProcess(IRenderControlFormContext renderContext) + { + ProcessForm?.Invoke(this, new FormEventArgs() { Context = renderContext }); + } + + /// + /// Raises the process event. + /// + /// The context in which the control is rendered. + protected virtual void OnProcessAndNextForm(IRenderControlFormContext renderContext) + { + ProcessAndNextForm?.Invoke(this, new FormEventArgs() { Context = renderContext }); + } + + /// + /// Raises the Initializations event. + /// + /// The context in which the control is rendered. + protected virtual void OnInitialize(IRenderControlFormContext renderContext) + { + InitializeForm?.Invoke(this, new FormEventArgs() { Context = renderContext }); + } + + /// + /// Raises the data delivery event. + /// + /// The context in which the control is rendered. + protected virtual void OnFill(IRenderControlFormContext renderContext) + { + FillForm?.Invoke(this, new FormEventArgs() { Context = renderContext }); + } + + /// + /// Raises the validation event. + /// + /// The event argument. + protected virtual void OnValidation(ValidationEventArgs e) + { + Validation?.Invoke(this, e); + } + + /// + /// Raises the Validated event. + /// + /// The event argument. + protected virtual void OnValidated(ValidationResultEventArgs e) + { + Validated?.Invoke(this, e); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs index 901eb6ca..3d9e0620 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs @@ -1,57 +1,57 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Abstract base class for form items. -// /// -// /// -// /// This class provides the base functionality for form items, including properties for the name of the input field, -// /// initialization, and rendering to HTML. -// /// -// public abstract class ControlFormItem : Control -// { -// /// -// /// Returns or sets the name of the input field. -// /// -// public string Name { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Abstract base class for form items. + /// + /// + /// This class provides the base functionality for form items, including properties for the name of the input field, + /// initialization, and rendering to HTML. + /// + public abstract class ControlFormItem : Control + { + /// + /// Returns or sets the name of the input field. + /// + public string Name { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItem(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItem(string id = null) + : base(id) + { + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public abstract void Initialize(RenderContextForm context); + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public abstract void Initialize(IRenderControlFormContext renderContext); -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public abstract IHtmlNode Render(RenderContextForm context); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public abstract IHtmlNode Render(IRenderControlFormContext renderContext); -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// if (context is RenderContextForm formContext) -// { -// return Render(formContext); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + if (renderContext is IRenderControlFormContext formContext) + { + return Render(formContext); + } -// return null; -// } -// } -//} + return null; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs index 60d18fd9..65377d37 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs @@ -1,165 +1,229 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemButton : ControlFormItem -// { -// /// -// /// Returns or sets the color of the button. -// /// -// public PropertyColorButton Color -// { -// get => (PropertyColorButton)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); -// } - -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeButton Size -// { -// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the Outline property. -// /// -// public bool Outline { get; set; } - -// /// -// /// Returns or sets whether the button should take up the full width. -// /// -// public TypeBlockButton Block -// { -// get => (TypeBlockButton)GetProperty(TypeBlockButton.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets whether the button is disabled. -// /// -// public bool Disabled { get; set; } - -// /// -// /// Returns or sets the content. -// /// -// public List Content { get; private set; } = new List(); - -// /// -// /// Event is triggered when the button is clicked. -// /// -// public EventHandler Click; - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the type. (button, submit, reset) -// /// -// public TypeButton Type { get; set; } = TypeButton.Default; - -// /// -// /// Returns or sets the value. -// /// -// public string Value { get; set; } - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemButton(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// Disabled = false; -// Size = TypeSizeButton.Default; - -// if (context.Request.HasParameter(Name)) -// { -// var value = context.Request.GetParameter(Name)?.Value; - -// if (!string.IsNullOrWhiteSpace(Value) && value == Value) -// { -// OnClickEvent(new FormEventArgs() { Context = context }); -// } -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var html = new HtmlElementFieldButton() -// { -// Id = Id, -// Name = Name, -// Type = Type.ToTypeString(), -// Value = Value, -// Class = Css.Concatenate("btn", GetClasses()), -// Style = GetStyles(), -// Role = Role, -// Disabled = Disabled, -// OnClick = OnClick?.ToString() -// }; - -// if (Icon != null && Icon.HasIcon) -// { -// html.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); -// } - -// if (Content.Count > 0) -// { -// html.Elements.AddRange(Content.Select(x => x.Render(context))); -// } - -// return html; -// } - -// /// -// /// Triggers the click event. -// /// -// /// The event argument. -// protected virtual void OnClickEvent(FormEventArgs e) -// { -// Click?.Invoke(this, e); -// } -// } -//} +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a button form item control. + /// + public class ControlFormItemButton : ControlFormItem + { + private readonly List _content = []; + + /// + /// Returns or sets the content. + /// + public IEnumerable Content => _content; + + /// + /// Returns or sets the color of the button. + /// + public PropertyColorButton Color + { + get => (PropertyColorButton)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); + } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the Outline property. + /// + public bool Outline { get; set; } + + /// + /// Returns or sets whether the button should take up the full width. + /// + public TypeBlockButton Block + { + get => (TypeBlockButton)GetProperty(TypeBlockButton.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets whether the button is disabled. + /// + public bool Disabled { get; set; } + + /// + /// Event is triggered when the button is clicked. + /// + public EventHandler Click; + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the type. (button, submit, reset) + /// + public TypeButton Type { get; set; } = TypeButton.Default; + + /// + /// Returns or sets the value. + /// + public string Value { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the button. + public ControlFormItemButton(string id = null, params IControl[] content) + : base(id) + { + _content.AddRange(content); + } + + /// + /// Adds one or more controls to the content. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var button = new ControlFormItemButton(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// button.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var button = new ControlFormItemButton(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// button.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public void Add(IEnumerable controls) + { + _content.AddRange(controls); + } + + /// + /// Removes a control from the content of the control panel. + /// + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the control panel. + /// + public void Remove(Control control) + { + _content.Remove(control); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + Disabled = false; + Size = TypeSizeButton.Default; + + if (renderContext.Request.HasParameter(Name)) + { + var value = renderContext.Request.GetParameter(Name)?.Value; + + if (!string.IsNullOrWhiteSpace(Value) && value == Value) + { + OnClickEvent(new FormEventArgs() { Context = renderContext }); + } + } + } + + /// + /// Convert to html. + /// + /// The context in which the control is rendered. + /// The control as html. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var html = new HtmlElementFieldButton() + { + Id = Id, + Name = Name, + Type = Type.ToTypeString(), + Value = Value, + Class = Css.Concatenate("btn", GetClasses()), + Style = GetStyles(), + Role = Role, + Disabled = Disabled, + OnClick = OnClick?.ToString() + }; + + if (Icon != null && Icon.HasIcon) + { + html.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + html.Add(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))); + } + + if (_content.Count > 0) + { + html.Add(Content.Select(x => x.Render(renderContext))); + } + + return html; + } + + /// + /// Triggers the click event. + /// + /// The event argument. + protected virtual void OnClickEvent(FormEventArgs e) + { + Click?.Invoke(this, e); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs index b1f767a0..705227e2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButtonSubmit.cs @@ -1,23 +1,25 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemButtonSubmit : ControlFormItemButton -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The control id. -// public ControlFormItemButtonSubmit(string id) -// : base(id) -// { -// Name = Id; -// Text = I18N.Translate("webexpress.webui", "form.submit.label"); -// Icon = new PropertyIcon(TypeIcon.Save); -// Color = new PropertyColorButton(TypeColorButton.Success); -// Type = TypeButton.Submit; -// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); -// OnClick = new PropertyOnClick($"$('#{Id}').val('submit');"); -// } -// } -//} +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a submit button form item control. + /// + public class ControlFormItemButtonSubmit : ControlFormItemButton + { + /// + /// Initializes a new instance of the class. + /// + /// The control id. + /// The child controls to be added to the button. + public ControlFormItemButtonSubmit(string id = null, params IControl[] content) + : base(id, content) + { + Name = Id; + Text = "webexpress.webui:form.submit.label"; + Icon = new PropertyIcon(TypeIcon.Save); + Color = new PropertyColorButton(TypeColorButton.Success); + Type = TypeButton.Submit; + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); + OnClick = new PropertyOnClick($"$('#{Id}').val('submit');"); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs index 6277f687..89c173c2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs @@ -1,114 +1,141 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation -// { -// /// -// /// Returns or sets the form items. -// /// -// public ICollection Items { get; } = new List(); - -// /// -// /// Determines whether the inputs are valid. -// /// -// public ICollection ValidationResults { get; } = new List(); - -// /// -// /// Returns or sets whether the form element has been validated. -// /// -// private bool IsValidated { get; set; } - -// /// -// /// Returns the most serious validation result. -// /// -// public virtual TypesInputValidity ValidationResult -// { -// get -// { -// var buf = ValidationResults; - -// if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) -// { -// return TypesInputValidity.Error; -// } -// else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) -// { -// return TypesInputValidity.Warning; -// } -// else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) -// { -// return TypesInputValidity.Success; -// } - -// return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; -// } -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroup(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form item. -// public ControlFormItemGroup(string id, params ControlFormItem[] item) -// : base(id) -// { -// (Items as List).AddRange(item); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form item. -// public ControlFormItemGroup(params ControlFormItem[] item) -// : base(null) -// { -// (Items as List).AddRange(item); -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var groupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(groupContex); -// } -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public virtual void Validate(RenderContextForm context) -// { -// var validationResults = ValidationResults as List; - -// validationResults.Clear(); - -// foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) -// { -// v.Validate(context); - -// validationResults.AddRange(v.ValidationResults); -// } -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Grouping of controls. + /// + public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation + { + private readonly List _items = []; + + /// + /// Returns the form items. + /// + public ICollection Items => _items; + + /// + /// Determines whether the inputs are valid. + /// + public ICollection ValidationResults { get; } = new List(); + + /// + /// Returns or sets whether the form element has been validated. + /// + private bool IsValidated { get; set; } + + /// + /// Returns the most serious validation result. + /// + public virtual TypesInputValidity ValidationResult + { + get + { + var buf = ValidationResults; + + if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) + { + return TypesInputValidity.Error; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) + { + return TypesInputValidity.Warning; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) + { + return TypesInputValidity.Success; + } + + return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form item. + public ControlFormItemGroup(string id = null, params ControlFormItem[] item) + : base(id) + { + _items.AddRange(item); + } + + /// + /// Adds a collection of form entries to the existing items. + /// + /// The form entries to add. + /// + /// This method appends the specified collection of instances to the + /// current list of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// This method accepts any item that derives from . + /// + public void Add(params ControlFormItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds a collection of form entries to the existing items. + /// + /// The form entries to add. + /// + /// This method appends the specified collection of instances to the + /// current form of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// This method accepts any item that derives from . + /// + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Removes a specified form entry from the existing items. + /// + /// The form entry to remove. + /// + /// This method removes the specified instance from the + /// current form of items. If the item does not exist in the list, the method does nothing. + /// This method accepts any item that derives from . + /// + public void Remove(ControlFormItem item) + { + _items.Remove(item); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var groupContex = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(groupContex); + } + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public virtual void Validate(IRenderControlFormContext renderContext) + { + var validationResults = ValidationResults as List; + + validationResults.Clear(); + + foreach (var v in Items.Where(x => x is IFormValidation).Select(x => x as IFormValidation)) + { + v.Validate(renderContext); + + validationResults.AddRange(v.ValidationResults); + } + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs index 335b5a34..60fd419b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs @@ -1,129 +1,122 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupColumn : ControlFormItemGroup -// { -// /// -// /// Returns the percentage distribution of the columns. -// /// -// public ICollection Distribution { get; set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupColumn(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupColumn(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupColumn(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-horizontal", GetClasses()), -// Style = GetStyles(), -// }; - -// var body = new HtmlElementTextContentDiv() { }; - -// foreach (var item in Items) -// { -// var row = new HtmlElementTextContentDiv() { }; - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// label.Classes.Add("me-2"); -// help.Text = I18N.Translate(input?.Help); -// help.Classes.Add("ms-2"); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); - -// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); -// } - -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); - -// if (input != null) -// { -// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); -// } -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv()); -// row.Elements.Add(item.Render(context)); -// row.Elements.Add(new HtmlElementTextContentDiv()); -// } - -// body.Elements.Add(row); -// } - -// html.Elements.Add(body); - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a column group of form items. + /// + public class ControlFormItemGroupColumn : ControlFormItemGroup + { + private readonly List _distribution = []; + + /// + /// Returns the percentage distribution of the columns. + /// + public IEnumerable Distribution => _distribution; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupColumn(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes a new instance of the class. + /// + ///The form controls. + public ControlFormItemGroupColumn(params ControlFormItem[] items) + : base(null, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var grpupContex = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(grpupContex); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-horizontal", GetClasses()), + Style = GetStyles(), + }; + + var body = new HtmlElementTextContentDiv() { }; + + foreach (var item in Items) + { + var row = new HtmlElementTextContentDiv() { }; + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + + label.Initialize(renderContext); + help.Initialize(renderContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + label.Classes.Add("me-2"); + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + help.Classes.Add("ms-2"); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + + row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); + } + else + { + row.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); + } + + row.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); + + if (input != null) + { + row.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); + } + } + else + { + row.Add(new HtmlElementTextContentDiv()); + row.Add(item.Render(renderGroupContext)); + row.Add(new HtmlElementTextContentDiv()); + } + + body.Add(row); + } + + html.Add(body); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs index d4f72edc..75a0eecb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs @@ -1,142 +1,133 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupColumnHorizontal : ControlFormItemGroupColumn -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupColumnHorizontal(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupColumnHorizontal(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-column-horizontal", GetClasses()), -// Style = GetStyles(), -// }; - -// var max = 100; -// var offset = 0; - -// foreach (var item in Items) -// { -// var div = new HtmlElementTextContentDiv() { Style = "" }; -// var width = -1; - -// if (Distribution.Count > offset) -// { -// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); -// div.Style = $"width: {width}%"; -// max -= width; - -// offset++; -// } -// else if (Items.Count > offset) -// { -// width = max / (Items.Count - offset); -// div.Style = $"width: {width}%"; -// } - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); -// //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; -// var row = new HtmlElementTextContentDiv() { Class = "" }; -// var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; -// var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// help.Text = I18N.Translate(input?.Help); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); -// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) -// { -// Style = "display: flex;" -// }); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); -// } - -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); - -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); -// } - -// div.Elements.Add(table); -// } -// else -// { -// div.Elements.Add(item.Render(renderContext)); -// } - -// html.Elements.Add(div); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a horizontal column group of form items. + /// + public class ControlFormItemGroupColumnHorizontal : ControlFormItemGroupColumn + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupColumnHorizontal(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes a new instance of the class. + /// + ///The form controls. + public ControlFormItemGroupColumnHorizontal(params ControlFormItem[] items) + : base(null, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-column-horizontal", GetClasses()), + Style = GetStyles(), + }; + + var max = 100; + var offset = 0; + + foreach (var item in Items) + { + var div = new HtmlElementTextContentDiv() { Style = "" }; + var width = -1; + + if (Distribution.Count() > offset) + { + width = Distribution.Skip(offset).Take(1).FirstOrDefault(); + div.Style = $"width: {width}%"; + max -= width; + + offset++; + } + else if (Items.Count > offset) + { + width = max / (Items.Count - offset); + div.Style = $"width: {width}%"; + } + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; + var row = new HtmlElementTextContentDiv() { Class = "" }; + var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; + var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; + + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderGroupContext)) + { + Style = "display: flex;" + }); + } + else + { + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + } + + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext))); + } + + div.Add(table); + } + else + { + div.Add(item.Render(renderGroupContext)); + } + + html.Add(div); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs index 3b0e86cb..7ecb07c7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs @@ -1,144 +1,126 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupColumnMix : ControlFormItemGroupColumn -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupColumnMix(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupColumnMix(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupColumnMix(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-column-mix", GetClasses()), -// Style = GetStyles(), -// }; - -// var max = 100; -// var offset = 0; - -// foreach (var item in Items) -// { -// var div = new HtmlElementTextContentDiv() { Style = "" }; -// var width = -1; - -// if (Distribution.Count > offset) -// { -// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); -// div.Style = $"width: {width}%"; -// max -= width; - -// offset++; -// } -// else if (Items.Count > offset) -// { -// width = max / (Items.Count - offset); -// div.Style = $"width: {width}%"; -// } - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); -// //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; -// var row = new HtmlElementTextContentDiv() { Class = "" }; -// var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; -// var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// help.Text = I18N.Translate(input?.Help); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); -// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) -// { -// Style = "display: flex;" -// }); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); -// } - -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); -// } - -// div.Elements.Add(table); -// } -// else -// { -// div.Elements.Add(item.Render(context)); -// } - -// html.Elements.Add(div); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a mix of form item group columns. + /// + public class ControlFormItemGroupColumnMix : ControlFormItemGroupColumn + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupColumnMix(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-column-mix", GetClasses()), + Style = GetStyles(), + }; + + var max = 100; + var offset = 0; + + foreach (var item in Items) + { + var div = new HtmlElementTextContentDiv() { Style = "" }; + var width = -1; + + if (Distribution.Count() > offset) + { + width = Distribution.Skip(offset).Take(1).FirstOrDefault(); + div.Style = $"width: {width}%"; + max -= width; + + offset++; + } + else if (Items.Count > offset) + { + width = max / (Items.Count - offset); + div.Style = $"width: {width}%"; + } + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + //var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; + var row = new HtmlElementTextContentDiv() { Class = "" }; + var body = new HtmlElementTextContentDiv(row) { Class = "form-group" }; + var table = new HtmlElementTextContentDiv(body) { Class = "form-group-horizontal" }; + + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + { + Style = "display: flex;" + }); + } + else + { + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + } + + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext), help.Render(renderGroupContext))); + } + else + { + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + } + + div.Add(table); + } + else + { + div.Add(item.Render(renderGroupContext)); + } + + html.Add(div); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs index eaac72ec..d08fa050 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs @@ -1,139 +1,121 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupColumnVertical : ControlFormItemGroupColumn -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupColumnVertical(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupColumnVertical(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupColumnVertical(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-column", GetClasses()), -// Style = GetStyles(), -// }; - -// var max = 100; -// var offset = 0; - -// foreach (var item in Items) -// { -// var div = new HtmlElementTextContentDiv() { Style = "" }; -// var width = -1; - -// if (Distribution.Count > offset) -// { -// width = Distribution.Skip(offset).Take(1).FirstOrDefault(); -// div.Style = $"width: {width}%"; -// max = max - width; - -// offset++; -// } -// else if (Items.Count > offset) -// { -// width = max / (Items.Count - offset); -// div.Style = $"width: {width}%"; -// } - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); -// var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// help.Text = I18N.Translate(input?.Help); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); -// fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) -// { -// Style = "display: flex;" -// }); -// } -// else -// { -// fieldset.Elements.Add(label.Render(renderContext)); -// } - -// fieldset.Elements.Add(item.Render(renderContext)); - -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// fieldset.Elements.Add(help.Render(renderContext)); -// } - -// div.Elements.Add(fieldset); -// } -// else -// { -// div.Elements.Add(item.Render(context)); -// } - -// html.Elements.Add(div); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a vertical column group of form items. + /// + public class ControlFormItemGroupColumnVertical : ControlFormItemGroupColumn + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupColumnVertical(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-column", GetClasses()), + Style = GetStyles(), + }; + + var max = 100; + var offset = 0; + + foreach (var item in Items) + { + var div = new HtmlElementTextContentDiv() { Style = "" }; + var width = -1; + + if (Distribution.Count() > offset) + { + width = Distribution.Skip(offset).Take(1).FirstOrDefault(); + div.Style = $"width: {width}%"; + max = max - width; + + offset++; + } + else if (Items.Count > offset) + { + width = max / (Items.Count - offset); + div.Style = $"width: {width}%"; + } + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; + + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + { + Style = "display: flex;" + }); + } + else + { + fieldset.Add(label.Render(renderGroupContext)); + } + + fieldset.Add(item.Render(renderGroupContext)); + + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + fieldset.Add(help.Render(renderGroupContext)); + } + + div.Add(fieldset); + } + else + { + div.Add(item.Render(renderGroupContext)); + } + + html.Add(div); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs index 4db37df7..9e991ded 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs @@ -1,123 +1,105 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupHorizontal : ControlFormItemGroup -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupHorizontal(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupHorizontal(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupHorizontal(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-horizontal", GetClasses()), -// Style = GetStyles(), -// }; - -// var body = new HtmlElementTextContentDiv() { }; - -// foreach (var item in Items) -// { -// var row = new HtmlElementTextContentDiv() { }; - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// label.Classes.Add("me-2"); -// help.Text = I18N.Translate(input?.Help); -// help.Classes.Add("ms-2"); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); - -// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext)) { }); -// } - -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); - -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// row.Elements.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); -// } -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv()); -// row.Elements.Add(item.Render(context)); -// row.Elements.Add(new HtmlElementTextContentDiv()); -// } - -// body.Elements.Add(row); -// } - -// html.Elements.Add(body); - -// return html; -// } -// } -//} +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Grouping of controls in a horizontal layout. + /// + public class ControlFormItemGroupHorizontal : ControlFormItemGroup + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupHorizontal(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-horizontal", GetClasses()), + Style = GetStyles(), + }; + + var body = new HtmlElementTextContentDiv() { }; + + foreach (var item in Items) + { + var row = new HtmlElementTextContentDiv() { }; + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + label.Classes.Add("me-2"); + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + help.Classes.Add("ms-2"); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext)) { }); + } + else + { + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext)) { }); + } + + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext)) { }); + + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext))); + } + } + else + { + row.Add(new HtmlElementTextContentDiv()); + row.Add(item.Render(renderGroupContext)); + row.Add(new HtmlElementTextContentDiv()); + } + + body.Add(row); + } + + html.Add(body); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs index ec46804b..60083268 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs @@ -1,124 +1,106 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupMix : ControlFormItemGroup -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupMix(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupMix(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupMix(params ControlFormItem[] items) -// : base(null, items) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); - -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("form-group-mix", GetClasses()), -// Style = GetStyles(), -// }; - -// var body = new HtmlElementTextContentDiv() { }; - -// foreach (var item in Items) -// { -// var row = new HtmlElementTextContentDiv() { }; - -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); - -// label.Initialize(renderContext); -// help.Initialize(renderContext); - -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// label.Classes.Add("me-2"); -// help.Text = I18N.Translate(input?.Help); - -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); - -// row.Elements.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext))); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); -// } - -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext), help.Render(renderContext))); -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv(item.Render(renderContext))); -// } -// } -// else -// { -// row.Elements.Add(new HtmlElementTextContentDiv()); -// row.Elements.Add(item.Render(context)); -// row.Elements.Add(new HtmlElementTextContentDiv()); -// } - -// body.Elements.Add(row); -// } - -// html.Elements.Add(body); - -// return html; -// } -// } -//} +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Grouping of controls with mixed form items. + /// + public class ControlFormItemGroupMix : ControlFormItemGroup + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupMix(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("form-group-mix", GetClasses()), + Style = GetStyles(), + }; + + var body = new HtmlElementTextContentDiv() { }; + + foreach (var item in Items) + { + var row = new HtmlElementTextContentDiv() { }; + + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); + + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + label.Classes.Add("me-2"); + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); + + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext))); + } + else + { + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + } + + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext), help.Render(renderGroupContext))); + } + else + { + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + } + } + else + { + row.Add(new HtmlElementTextContentDiv()); + row.Add(item.Render(renderGroupContext)); + row.Add(new HtmlElementTextContentDiv()); + } + + body.Add(row); + } + + html.Add(body); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs index 1e7948d0..0831f399 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs @@ -1,116 +1,98 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grouping of controls. -// /// -// public class ControlFormItemGroupVertical : ControlFormItemGroup -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemGroupVertical(string id = null) -// : base(id) -// { -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Grouping of controls in a vertical layout. + /// + public class ControlFormItemGroupVertical : ControlFormItemGroup + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + ///The form controls. + public ControlFormItemGroupVertical(string id = null, params ControlFormItem[] items) + : base(id, items) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// ///The form controls. -// public ControlFormItemGroupVertical(string id, params ControlFormItem[] items) -// : base(id, items) -// { -// } + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); -// /// -// /// Initializes a new instance of the class. -// /// -// ///The form controls. -// public ControlFormItemGroupVertical(params ControlFormItem[] items) -// : base(null, items) -// { -// } + foreach (var item in Items) + { + item.Initialize(renderGroupContext); + } + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var grpupContex = new RenderContextFormGroup(context, this); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); -// foreach (var item in Items) -// { -// item.Initialize(grpupContex); -// } -// } + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + }; -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var renderContext = new RenderContextFormGroup(context, this); + foreach (var item in Items) + { + if (item is ControlFormItemInput input) + { + var icon = new ControlIcon() { Icon = input?.Icon }; + var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); + var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); + var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// }; + label.Initialize(renderGroupContext); + help.Initialize(renderGroupContext); -// foreach (var item in Items) -// { -// if (item is ControlFormItemInput input) -// { -// var icon = new ControlIcon() { Icon = input?.Icon }; -// var label = new ControlFormItemLabel(!string.IsNullOrEmpty(item.Id) ? item.Id + "_label" : string.Empty); -// var help = new ControlFormItemHelpText(!string.IsNullOrEmpty(item.Id) ? item.Id + "_help" : string.Empty); -// var fieldset = new HtmlElementFormFieldset() { Class = "form-group" }; + label.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Label); + label.FormItem = item; + help.Text = I18N.Translate(renderGroupContext.Request?.Culture, input?.Help); -// label.Initialize(renderContext); -// help.Initialize(renderContext); + if (icon.Icon != null) + { + icon.Classes.Add("me-2 pt-1"); + fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + { + Style = "display: flex;" + }); + } + else + { + fieldset.Add(label.Render(renderGroupContext)); + } -// label.Text = I18N.Translate(input?.Label); -// label.FormItem = item; -// help.Text = I18N.Translate(input?.Help); + fieldset.Add(item.Render(renderGroupContext)); -// if (icon.Icon != null) -// { -// icon.Classes.Add("me-2 pt-1"); -// fieldset.Elements.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderContext), label.Render(renderContext)) -// { -// Style = "display: flex;" -// }); -// } -// else -// { -// fieldset.Elements.Add(label.Render(renderContext)); -// } + if (!string.IsNullOrWhiteSpace(input?.Help)) + { + fieldset.Add(help.Render(renderGroupContext)); + } -// fieldset.Elements.Add(item.Render(renderContext)); + html.Add(fieldset); + } + else + { + html.Add(item?.Render(renderGroupContext)); + } + } -// if (!string.IsNullOrWhiteSpace(input?.Help)) -// { -// fieldset.Elements.Add(help.Render(renderContext)); -// } - -// html.Elements.Add(fieldset); -// } -// else -// { -// html.Elements.Add(item?.Render(context)); -// } -// } - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs index 4129a78c..4f2a99fa 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs @@ -1,67 +1,60 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemHelpText : ControlFormItem -// { -// /// -// /// Returns or sets the size of the text. -// /// -// public PropertySizeText Size -// { -// get => (PropertySizeText)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item that displays help text. + /// + public class ControlFormItemHelpText : ControlFormItem + { + /// + /// Returns or sets the size of the text. + /// + public PropertySizeText Size + { + get => (PropertySizeText)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } -// /// -// /// Returns or sets the help text. -// /// -// public string Text { get; set; } + /// + /// Returns or sets the help text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemHelpText(string id) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemHelpText(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlFormItemHelpText(string id, string text) -// : this(id) -// { -// Text = text; -// } + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + TextColor = new PropertyColorText(TypeColorText.Muted); + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// TextColor = new PropertyColorText(TypeColorText.Muted); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// return new HtmlElementTextSemanticsSmall() -// { -// Text = I18N.Translate(context.Culture, Text), -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + return new HtmlElementTextSemanticsSmall() + { + Id = Id, + Text = I18N.Translate(renderContext.Request?.Culture, Text), + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs index 11821782..650b267f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs @@ -1,152 +1,144 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using System.Linq; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Identifies a control that is to be filled in by the user. -// /// -// public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation -// { -// /// -// /// Event to validate the input values. -// /// -// public event EventHandler Validation; - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Returns or sets the label. -// /// -// public string Label { get; set; } - -// /// -// /// Returns or sets an optional help text. -// /// -// public string Help { get; set; } - -// /// -// /// Returns or sets whether the input element is disabled. -// /// -// public bool Disabled { get; set; } - -// /// -// /// Returns or sets the elements that are displayed in front of the control. -// /// -// public List Prepend { get; private set; } - -// /// -// /// Returns or sets the elements that are displayed after the control. -// /// -// public List Append { get; private set; } - -// /// -// /// Returns or sets whether the form element has been validated. -// /// -// private bool IsValidated { get; set; } - -// /// -// /// Returns or sets an object that is linked to the control. -// /// -// public object Tag { get; set; } - -// /// -// /// Determines whether the inputs are valid. -// /// -// public virtual ICollection ValidationResults { get; } = new List(); - -// /// -// /// Returns the most serious validation result. -// /// -// public virtual TypesInputValidity ValidationResult -// { -// get -// { -// var buf = ValidationResults; - -// if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) -// { -// return TypesInputValidity.Error; -// } -// else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) -// { -// return TypesInputValidity.Warning; -// } -// else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) -// { -// return TypesInputValidity.Success; -// } - -// return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; -// } -// } - -// /// -// /// Returns or sets the value. -// /// -// public virtual string Value { get; set; } = string.Empty; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInput(string id) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Prepend = new List(); -// Append = new List(); -// IsValidated = false; -// } - -// /// -// /// Initializes the form.emement -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// } - -// /// -// /// Raises the validation event. -// /// -// /// The event argument. -// protected virtual void OnValidation(ValidationEventArgs e) -// { -// Validation?.Invoke(this, e); -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public virtual void Validate(RenderContextForm context) -// { -// IsValidated = true; - -// if (ValidationResults is List validationResults) -// { -// validationResults.Clear(); - -// if (!Disabled) -// { -// var args = new ValidationEventArgs() { Value = Value, Context = context }; -// OnValidation(args); - -// validationResults.AddRange(args.Results); -// } -// } -// } -// } -//} +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Identifies a control that is to be filled in by the user. + /// + public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation + { + /// + /// Event to validate the input values. + /// + public event EventHandler Validation; + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the label. + /// + public string Label { get; set; } + + /// + /// Returns or sets an optional help text. + /// + public string Help { get; set; } + + /// + /// Returns or sets whether the input element is disabled. + /// + public bool Disabled { get; set; } + + /// + /// Returns or sets the elements that are displayed in front of the control. + /// + public List Prepend { get; private set; } + + /// + /// Returns or sets the elements that are displayed after the control. + /// + public List Append { get; private set; } + + /// + /// Returns or sets whether the form element has been validated. + /// + private bool IsValidated { get; set; } + + /// + /// Returns or sets an object that is linked to the control. + /// + public object Tag { get; set; } + + /// + /// Determines whether the inputs are valid. + /// + public virtual ICollection ValidationResults { get; } = new List(); + + /// + /// Returns the most serious validation result. + /// + public virtual TypesInputValidity ValidationResult + { + get + { + var buf = ValidationResults; + + if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) + { + return TypesInputValidity.Error; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) + { + return TypesInputValidity.Warning; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) + { + return TypesInputValidity.Success; + } + + return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; + } + } + + /// + /// Returns or sets the value. + /// + public virtual string Value { get; set; } = string.Empty; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInput(string id) + : base(id) + { + Prepend = new List(); + Append = new List(); + IsValidated = false; + } + + /// + /// Initializes the form emement. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } + + /// + /// Raises the validation event. + /// + /// The event argument. + protected virtual void OnValidation(ValidationEventArgs e) + { + Validation?.Invoke(this, e); + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public virtual void Validate(IRenderControlFormContext renderContext) + { + IsValidated = true; + + if (ValidationResults is List validationResults) + { + validationResults.Clear(); + + if (!Disabled) + { + var args = new ValidationEventArgs() { Value = Value, Context = renderContext }; + OnValidation(args); + + validationResults.AddRange(args.Results); + } + } + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs index 1fe31463..1337b072 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs @@ -4,7 +4,7 @@ //namespace WebExpress.WebUI.WebControl //{ -// public class ControlFormItemInputCheckbox : ControlFormItemInput +// public class ControlFormItemInputCheckBox : ControlFormItemInput // { // /// // /// Returns or sets whether the checkbox should be displayed on a new line. @@ -25,7 +25,7 @@ // /// Initializes a new instance of the class. // /// // /// The id. -// public ControlFormItemInputCheckbox(string id = null) +// public ControlFormItemInputCheckBox(string id = null) // : base(id) // { // Value = "false"; diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs index fead0d92..5226f00c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs @@ -1,54 +1,46 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; +ο»Ώusing WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputHidden : ControlFormItemInput -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputHidden(string id = null) -// : base(id) -// { -// Name = Id; -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a hidden input form item control. + /// + public class ControlFormItemInputHidden : ControlFormItemInput + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInputHidden(string id = null) + : base(id) + { + Name = Id; + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The name. -// public ControlFormItemInputHidden(string id, string name) -// : base(id) -// { -// Name = name; -// } + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + Value = renderContext?.Request.GetParameter(Name)?.Value; + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// Value = context?.Request.GetParameter(Name)?.Value; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// return new HtmlElementFieldInput() -// { -// Id = Id, -// Value = Value, -// Name = Name, -// Type = "hidden", -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + return new HtmlElementFieldInput() + { + Id = Id, + Value = Value, + Name = Name, + Type = "hidden", + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs index 089f0351..68881609 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs @@ -1,208 +1,199 @@ -ο»Ώ//using System; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebUri; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputTextBox : ControlFormItemInput -// { -// /// -// /// Determines whether the control is automatically initialized. -// /// -// public bool AutoInitialize { get; set; } - -// /// -// /// Determines whether it is a multi-line text box. -// /// -// public TypesEditTextFormat Format { get; set; } - -// /// -// /// Returns or sets the description. -// /// -// public string Description { get; set; } - -// /// -// /// Returns or sets a placeholder text. -// /// -// public string Placeholder { get; set; } - -// /// -// /// Returns or sets the minimum length. -// /// -// public int? MinLength { get; set; } - -// /// -// /// Returns or sets the maximum length. -// /// -// public int? MaxLength { get; set; } - -// /// -// /// Returns or sets whether inputs are enforced. -// /// -// public bool Required { get; set; } - -// /// -// /// Returns or sets a search pattern that checks the content. -// /// -// public string Pattern { get; set; } - -// /// -// /// Returns or sets the height of the text fiel (for Multiline and WYSIWYG) -// /// -// public int Rows { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputTextBox(string id = null) -// : base(id) -// { -// Name = Id; -// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The name of the text box. -// public ControlFormItemInputTextBox(string id, string name) -// : base(id) -// { -// Name = name; -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// base.Initialize(context); - -// Rows = 8; -// AutoInitialize = true; - -// Value = context?.Request.GetParameter(Name)?.Value; - -// if (Format == TypesEditTextFormat.Wysiwyg) -// { -// var contextPath = context?.PageContext?.ApplicationContext?.ContextPath; -// context.VisualTree.CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); -// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var id = Id ?? Guid.NewGuid().ToString(); - -// Classes.Add("form-control"); - -// if (Disabled) -// { -// Classes.Add("disabled"); -// } - -// switch (ValidationResult) -// { -// case TypesInputValidity.Warning: -// Classes.Add("input-warning"); -// break; -// case TypesInputValidity.Error: -// Classes.Add("input-error"); -// break; -// } - -// if (AutoInitialize && Format == TypesEditTextFormat.Wysiwyg && !string.IsNullOrWhiteSpace(Id)) -// { -// var initializeCode = $"$(document).ready(function() {{ $('#{id}').summernote({{ tabsize: 2, height: '{Rows}rem', lang: 'de-DE' }}); }});"; - -// context.AddScript(id, initializeCode); - -// AutoInitialize = false; -// } - -// return Format switch -// { -// TypesEditTextFormat.Multiline => new HtmlElementFormTextarea() -// { -// Id = Id, -// Value = Value, -// Name = Name, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// Placeholder = I18N.Translate(context.Culture, Placeholder), -// Rows = Rows.ToString() -// }, -// TypesEditTextFormat.Wysiwyg => new HtmlElementFormTextarea() -// { -// Id = id, -// Value = Value, -// Name = Name, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// Placeholder = I18N.Translate(context.Culture, Placeholder), -// Rows = Rows.ToString() -// }, -// _ => new HtmlElementFieldInput() -// { -// Id = Id, -// Value = Value, -// Name = Name, -// MinLength = MinLength?.ToString(), -// MaxLength = MaxLength?.ToString(), -// Required = Required, -// Pattern = Pattern, -// Type = "text", -// Disabled = Disabled, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// Placeholder = I18N.Translate(context.Culture, Placeholder) -// }, -// }; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); - -// if (Disabled) -// { -// return; -// } - -// if (Required && string.IsNullOrWhiteSpace(base.Value)) -// { -// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); - -// return; -// } - -// if (!string.IsNullOrWhiteSpace(MinLength?.ToString()) && Convert.ToInt32(MinLength) > base.Value.Length) -// { -// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(context.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); -// } - -// if (!string.IsNullOrWhiteSpace(MaxLength?.ToString()) && Convert.ToInt32(MaxLength) < base.Value.Length) -// { -// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(context.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); -// } -// } -// } -//} +ο»Ώusing System; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a text box input form item control. + /// + public class ControlFormItemInputTextBox : ControlFormItemInput + { + /// + /// Determines whether the control is automatically initialized. + /// + public bool AutoInitialize { get; set; } + + /// + /// Determines whether it is a multi-line text box. + /// + public TypesEditTextFormat Format { get; set; } + + /// + /// Returns or sets the description. + /// + public string Description { get; set; } + + /// + /// Returns or sets a placeholder text. + /// + public string Placeholder { get; set; } + + /// + /// Returns or sets the minimum length. + /// + public uint? MinLength { get; set; } + + /// + /// Returns or sets the maximum length. + /// + public uint? MaxLength { get; set; } + + /// + /// Returns or sets whether inputs are enforced. + /// + public bool Required { get; set; } + + /// + /// Returns or sets a search pattern that checks the content. + /// + public string Pattern { get; set; } + + /// + /// Returns or sets the height of the text field (for Multiline and WYSIWYG). + /// + public uint? Rows { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInputTextBox(string id = null) + : base(id) + { + Name = Id; + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + base.Initialize(renderContext); + + Rows = 8; + AutoInitialize = true; + + Value = renderContext?.Request.GetParameter(Name)?.Value; + + if (Format == TypesEditTextFormat.Wysiwyg) + { + var contextPath = renderContext?.PageContext?.ApplicationContext?.ContextPath; + //renderContext.AddCssLinks(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); + //renderContext.AddHeaderScriptLinks(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var id = Id ?? Guid.NewGuid().ToString(); + + Classes.Add("form-control"); + + if (Disabled) + { + Classes.Add("disabled"); + } + + switch (ValidationResult) + { + case TypesInputValidity.Warning: + Classes.Add("input-warning"); + break; + case TypesInputValidity.Error: + Classes.Add("input-error"); + break; + } + + if (AutoInitialize && Format == TypesEditTextFormat.Wysiwyg && !string.IsNullOrWhiteSpace(Id)) + { + var initializeCode = $"$(document).ready(function() {{ $('#{id}').summernote({{ tabsize: 2, height: '{Rows}rem', lang: 'de-DE' }}); }});"; + + renderContext.AddScript(id, initializeCode); + + AutoInitialize = false; + } + + return Format switch + { + TypesEditTextFormat.Multiline => new HtmlElementFormTextarea() + { + Id = Id, + Value = Value, + Name = Name, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + Placeholder = I18N.Translate(renderContext.Request?.Culture, Placeholder), + Rows = Rows.ToString() + }, + TypesEditTextFormat.Wysiwyg => new HtmlElementFormTextarea() + { + Id = id, + Value = Value, + Name = Name, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + Placeholder = I18N.Translate(renderContext.Request?.Culture, Placeholder), + Rows = Rows.ToString() + }, + _ => new HtmlElementFieldInput() + { + Id = Id, + Value = Value, + Name = Name, + MinLength = MinLength?.ToString(), + MaxLength = MaxLength?.ToString(), + Required = Required, + Pattern = Pattern, + Type = "text", + Disabled = Disabled, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + Placeholder = I18N.Translate(renderContext.Request?.Culture, Placeholder) + }, + }; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + + if (Disabled) + { + return; + } + + if (Required && string.IsNullOrWhiteSpace(base.Value)) + { + ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); + + return; + } + + if (!string.IsNullOrWhiteSpace(MinLength?.ToString()) && Convert.ToInt32(MinLength) > base.Value.Length) + { + ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); + } + + if (!string.IsNullOrWhiteSpace(MaxLength?.ToString()) && Convert.ToInt32(MaxLength) < base.Value.Length) + { + ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); + } + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs index a5215994..47a7f11b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs @@ -1,67 +1,60 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemLabel : ControlFormItem -// { -// /// -// /// Returns or sets the text of the label. -// /// -// public string Text { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a label for a form item control. + /// + public class ControlFormItemLabel : ControlFormItem + { + /// + /// Returns or sets the text of the label. + /// + public string Text { get; set; } -// /// -// /// Returns or sets the associated form field. -// /// -// public ControlFormItem FormItem { get; set; } + /// + /// Returns or sets the associated form field. + /// + public ControlFormItem FormItem { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemLabel(string id) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemLabel(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlFormItemLabel(string id, string text) -// : this(id) -// { -// Text = text; -// } + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// return new HtmlElementFieldLabel() -// { -// Text = I18N.Translate(context.Culture, Text), -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role, -// For = FormItem != null ? -// string.IsNullOrWhiteSpace(FormItem.Id) ? -// FormItem.Name : -// FormItem.Id : -// null -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + return new HtmlElementFieldLabel() + { + Id = Id, + Text = I18N.Translate(renderContext.Request?.Culture, Text), + Class = GetClasses(), + Style = GetStyles(), + Role = Role, + For = FormItem != null ? + string.IsNullOrWhiteSpace(FormItem.Id) ? + FormItem.Name : + FormItem.Id : + null + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index ab4c19a7..487b5133 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -12,7 +12,15 @@ namespace WebExpress.WebUI.WebControl /// public class ControlLink : Control, IControlLink { - private readonly List _children = []; + private readonly List _controls = []; + + /// + /// Returns the content of the control. + /// + /// + /// An enumerable collection of child controls. + /// + public IEnumerable Controls => _controls; /// /// Returns or sets whether the link is active or not. @@ -67,11 +75,6 @@ public TypeTextDecoration Decoration /// public string Tooltip { get; set; } - /// - /// Returns or sets the content. - /// - public IEnumerable Children => _children; - /// /// Returns or sets the parameters that apply to the link. /// @@ -103,25 +106,51 @@ public PropertySizeText Size public ControlLink(string id = null, params IControl[] content) : base(id) { - _children.AddRange(content); + _controls.AddRange(content); } /// - /// Adds one or more children to the link. + /// Adds one or more controls to the content. /// - /// The children to add to the split button. - public void Add(params IControl[] children) + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var link = new ControlLink(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// link.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public void Add(params IControl[] controls) { - _children.AddRange(children); + _controls.AddRange(controls); } /// - /// Adds one or more children to the link. + /// Adds one or more controls to the content. /// - /// The children to add to the split button. - public void Add(IEnumerable children) + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of the control panel. + /// It is useful for dynamically constructing the user interface by appending various controls to the panel's content. + /// + /// Example usage: + /// + /// var link = new ControlLink(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// link.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public void Add(IEnumerable controls) { - _children.AddRange(children); + _controls.AddRange(controls); } /// @@ -164,7 +193,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) { var param = GetParams(renderContext?.Request); - var html = new HtmlElementTextSemanticsA(_children.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(_controls.Select(x => x.Render(renderContext)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index 03480bf3..b5b10c16 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -1,95 +1,143 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a control list that can contain multiple control list items. - /// - public class ControlList : Control - { - /// - /// Returns or sets the layout. - /// - public TypeLayoutList Layout - { - get => (TypeLayoutList)GetProperty(TypeLayoutList.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the list entries. - /// - public IEnumerable Items { get; private set; } = []; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The list entries. - public ControlList(string id = null, params ControlListItem[] items) - : base(id) - { - Items = items ?? []; - } - - /// - /// Adds list entries. - /// - /// The list entries. - public void Add(IEnumerable items) - { - Items = Items.Concat(items); - } - - /// - /// Adds list entries. - /// - /// The list entry. - public void Add(ControlListItem item) - { - Items = Items.Concat([item]); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// - public override IHtmlNode Render(IRenderControlContext renderContext) - { - return Render(renderContext, Items); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// The list entries. - /// An HTML node representing the rendered control. - public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) - { - var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); - switch (Layout) - { - case TypeLayoutList.Horizontal: - case TypeLayoutList.Flush: - case TypeLayoutList.Group: - li.ForEach(x => x.AddClass("list-group-item")); - break; - } - - var html = new HtmlElementTextContentUl(li.ToArray()) - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - return html; - } - } -} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control list that can contain multiple control list items. + /// + public class ControlList : Control + { + private readonly List _items = []; + + /// + /// Returns the list entries. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the layout. + /// + public TypeLayoutList Layout + { + get => (TypeLayoutList)GetProperty(TypeLayoutList.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The list entries. + public ControlList(string id = null, params ControlListItem[] items) + : base(id) + { + _items.AddRange(items); + } + + /// + /// Adds a collection of list entries to the existing items. + /// + /// The list entries to add. + /// + /// This method appends the specified collection of instances to the + /// current list of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// var item2 = new ControlListItem { Text = "Item 2" }; + /// list.Add(item1, item2); + /// + /// This method accepts any item that derives from . + /// + public void Add(params ControlListItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds a collection of list entries to the existing items. + /// + /// The list entries to add. + /// + /// This method appends the specified collection of instances to the + /// current list of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// var item2 = new ControlListItem { Text = "Item 2" }; + /// list.Add(new List([ item1, item2 ])); + /// + /// This method accepts any item that derives from . + /// + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Removes a specified list entry from the existing items. + /// + /// The list entry to remove. + /// + /// This method removes the specified instance from the + /// current list of items. If the item does not exist in the list, the method does nothing. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// list.Add(item1); + /// list.Remove(item1); + /// + /// This method accepts any item that derives from . + /// + public void Remove(ControlListItem item) + { + _items.Remove(item); + } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return Render(renderContext, Items); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// The list entries. + /// An HTML node representing the rendered control. + public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + { + var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); + switch (Layout) + { + case TypeLayoutList.Horizontal: + case TypeLayoutList.Flush: + case TypeLayoutList.Group: + li.ForEach(x => x.AddClass("list-group-item")); + break; + } + + var html = new HtmlElementTextContentUl(li.ToArray()) + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 6407341d..3557b902 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -1,91 +1,125 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. - /// - public class ControlPanel : Control - { - private readonly List _content = []; - - /// - /// Returns the content of the panel. - /// - /// - /// The content property holds a collection of controls that represent the visual and interactive elements - /// within this container. - /// - public IEnumerable Content => _content; - - /// - /// Returns or sets the arrangement of the content. - /// - public TypeDirection Direction - { - get => (TypeDirection)GetProperty(TypeDirection.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Fixed or full-width adjustment. - /// - public TypePanelContainer Fluid - { - get => (TypePanelContainer)GetProperty(TypePanelContainer.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The child controls to be added to the panel. - public ControlPanel(string id = null, params IControl[] children) - : base(id) - { - _content.AddRange(children.Where(x => x != null)); - } - - /// - /// Adds one or more controls to the content of the control panel. - /// - /// The controls to add to the content. - /// - /// This method allows adding one or multiple controls to the collection of - /// the control panel. It is useful for dynamically constructing the user interface by appending - /// various controls to the panel's content. - /// Example usage: - /// - /// var panel = new ControlPanel(); - /// var button1 = new ControlText { Text = "Save" }; - /// var button2 = new ControlText { Text = "Cancel" }; - /// panel.Add(button1, button2); - /// - /// This method accepts any control that implements the interface. - /// - public virtual void Add(params IControl[] children) - { - _content.AddRange(children); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) - { - return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. + /// + public class ControlPanel : Control + { + private readonly List _content = []; + + /// + /// Returns the content of the panel. + /// + /// + /// The content property holds a collection of controls that represent the visual and interactive elements + /// within this container. + /// + public IEnumerable Content => _content; + + /// + /// Returns or sets the arrangement of the content. + /// + public TypeDirection Direction + { + get => (TypeDirection)GetProperty(TypeDirection.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Fixed or full-width adjustment. + /// + public TypePanelContainer Fluid + { + get => (TypePanelContainer)GetProperty(TypePanelContainer.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel. + public ControlPanel(string id = null, params IControl[] children) + : base(id) + { + _content.AddRange(children.Where(x => x != null)); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// panel.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// panel.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _content.AddRange(controls); + } + + /// + /// Removes a control from the content of the control panel. + /// + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the control panel. + /// + public void Remove(Control control) + { + _content.Remove(control); + } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs index f87ae725..25a7ab2a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs @@ -1,154 +1,123 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlProgressBar : Control -// { -// /// -// /// Returns or sets the format of the progress bar. -// /// -// public TypeFormatProgress Format { get; set; } - -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeProgress Size -// { -// get => (TypeSizeProgress)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass(), () => value.ToStyle()); -// } - -// /// -// /// Returns or sets the progress bar color. -// /// -// public PropertyColorProgress Color { get; set; } - -// /// -// /// Returns or sets the text color. -// /// -// public new PropertyColorText TextColor { get; set; } - -// /// -// /// Returns or sets the value. -// /// -// public int Value { get; set; } - -// /// -// /// Returns or sets the minimum value. -// /// -// public int Min { get; set; } - -// /// -// /// Returns or sets the maximum value. -// /// -// public int Max { get; set; } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlProgressBar(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The value. -// public ControlProgressBar(string id, int value) -// : this(id) -// { -// Value = value; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The value. -// public ControlProgressBar(string id, int value, int min = 0, int max = 100) -// : this(id) -// { -// Value = value; -// Min = min; -// Max = max; -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Min = 0; -// Max = 100; -// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Default); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// if (Format == TypeFormatProgress.Default) -// { -// return new HtmlElementFormProgress(Value + "%") -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role, -// Min = Min.ToString(), -// Max = Max.ToString(), -// Value = Value.ToString() -// }; -// } - -// var bar = new HtmlElementTextContentDiv(new HtmlText(Text)) -// { -// Role = "progressbar", -// Class = Css.Concatenate -// ( -// "progress-bar", -// Color?.ToClass(), -// TextColor?.ToClass(), -// Format.ToClass() -// ), -// Style = Css.Concatenate -// ( -// "width: " + Value + "%;", -// Color?.ToStyle(), -// TextColor?.ToStyle() -// ) -// }; -// bar.AddUserAttribute("aria-valuenow", Value.ToString()); -// bar.AddUserAttribute("aria-valuemin", Min.ToString()); -// bar.AddUserAttribute("aria-valuemax", Max.ToString()); - -// var html = new HtmlElementTextContentDiv(bar) -// { -// Id = Id, -// Role = Role, -// Class = Css.Concatenate -// ( -// "progress", -// GetClasses() -// ), -// Style = GetStyles() -// }; - -// return html; - -// } -// } -//} +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a progress bar control. + /// + public class ControlProgressBar : Control + { + /// + /// Returns or sets the format of the progress bar. + /// + public TypeFormatProgress Format { get; set; } + + /// + /// Returns or sets the size. + /// + public TypeSizeProgress Size + { + get => (TypeSizeProgress)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass(), () => value.ToStyle()); + } + + /// + /// Returns or sets the progress bar color. + /// + public PropertyColorProgress Color { get; set; } + + /// + /// Returns or sets the text color. + /// + public new PropertyColorText TextColor { get; set; } + + /// + /// Returns or sets the value. + /// + public int Value { get; set; } + + /// + /// Returns or sets the minimum value. + /// + public uint Min { get; set; } = 0; + + /// + /// Returns or sets the maximum value. + /// + public uint Max { get; set; } = 100; + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlProgressBar(string id = null) + : base(id) + { + BackgroundColor = new PropertyColorBackground(TypeColorBackground.Default); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + if (Format == TypeFormatProgress.Default) + { + return new HtmlElementFormProgress(Value + "%") + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role, + Min = Min.ToString(), + Max = Max.ToString(), + Value = Value.ToString() + }; + } + + var bar = new HtmlElementTextContentDiv(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))) + { + Role = "progressbar", + Class = Css.Concatenate + ( + "progress-bar", + Color?.ToClass(), + TextColor?.ToClass(), + Format.ToClass() + ), + Style = Css.Concatenate + ( + "width: " + Value + "%;", + Color?.ToStyle(), + TextColor?.ToStyle() + ) + }; + bar.AddUserAttribute("aria-valuenow", Value.ToString()); + bar.AddUserAttribute("aria-valuemin", Min.ToString()); + bar.AddUserAttribute("aria-valuemax", Max.ToString()); + + var html = new HtmlElementTextContentDiv(bar) + { + Id = Id, + Role = Role, + Class = Css.Concatenate + ( + "progress", + GetClasses() + ), + Style = GetStyles() + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/FormEventArgs.cs b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs index 710e2751..de5e78c9 100644 --- a/src/WebExpress.WebUI/WebControl/FormEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/FormEventArgs.cs @@ -1,22 +1,22 @@ -ο»Ώ//using System; +ο»Ώusing System; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Event argument for forms. -// /// -// public class FormEventArgs : EventArgs -// { -// /// -// /// The form context. -// /// -// public RenderContextForm Context { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Event argument for forms. + /// + public class FormEventArgs : EventArgs + { + /// + /// The form render context. + /// + public IRenderControlFormContext Context { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// public FormEventArgs() -// { -// } -// } -//} + /// + /// Initializes a new instance of the class. + /// + public FormEventArgs() + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/IControlForm.cs b/src/WebExpress.WebUI/WebControl/IControlForm.cs index 731b62bb..89e5110b 100644 --- a/src/WebExpress.WebUI/WebControl/IControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/IControlForm.cs @@ -1,90 +1,106 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using WebExpress.WebCore.WebMessage; +ο»Ώusing System; +using System.Collections.Generic; +using WebExpress.WebCore.WebMessage; -//namespace WebExpress.WebUI.WebControl -//{ -// public interface IControlForm : IControl -// { -// /// -// /// Event to validate the input values. -// /// -// event EventHandler Validation; +namespace WebExpress.WebUI.WebControl +{ + /// + /// Interface for a form control, extending the base control interface. + /// + public interface IControlForm : IControl + { + /// + /// Event to validate the input values. + /// + event EventHandler Validation; -// /// -// /// Event is raised when the form has been initialized. -// /// -// event EventHandler InitializeForm; + /// + /// Event is raised when the form has been initialized. + /// + event EventHandler InitializeForm; -// /// -// /// Event is raised when the form's data needs to be determined. -// /// -// event EventHandler FillForm; + /// + /// Event is raised when the form's data needs to be determined. + /// + event EventHandler FillForm; -// /// -// /// Event is raised when the form is about to be processed. -// /// -// event EventHandler ProcessForm; + /// + /// Event is raised when the form is about to be processed. + /// + event EventHandler ProcessForm; -// /// -// /// Event is raised when the form is to be processed and the next data is to be loaded. -// /// -// event EventHandler ProcessAndNextForm; + /// + /// Event is raised when the form is to be processed and the next data is to be loaded. + /// + event EventHandler ProcessAndNextForm; -// /// -// /// Returns or sets the name of the form. -// /// -// string Name { get; set; } + /// + /// Returns or sets the name of the form. + /// + string Name { get; set; } -// /// -// /// Returns or sets the target uri. -// /// -// string Uri { get; set; } + /// + /// Returns or sets the target uri. + /// + string Uri { get; set; } -// /// -// /// Returns or sets the redirect uri. -// /// -// string RedirectUri { get; set; } + /// + /// Returns or sets the redirect uri. + /// + string RedirectUri { get; set; } -// /// -// /// Returns or sets the form items. -// /// -// IEnumerable Items { get; } + /// + /// Returns or sets the form items. + /// + IEnumerable Items { get; } -// /// -// /// Returns or sets the request method. -// /// -// RequestMethod Method { get; set; } + /// + /// Returns or sets the request method. + /// + RequestMethod Method { get; set; } -// /// -// /// Initializes the form. -// /// -// /// The context in which the control is rendered. -// void Initialize(RenderContextForm context); + ///// + ///// Initializes the form. + ///// + ///// The context in which the control is rendered. + //void Initialize(RenderContextForm renderContext); -// /// -// /// Pre-processes the form. -// /// -// /// The context in which the control is rendered. -// void PreProcess(RenderContextForm context); + ///// + ///// Pre-processes the form. + ///// + ///// The context in which the control is rendered. + //void PreProcess(RenderContextForm renderContext); -// /// -// /// Adds form control items to the form. -// /// -// /// The form items. -// void Add(params ControlFormItem[] item); + /// + /// Adds one or more form control items to the form. + /// + /// The form control items to add to the form. + /// + /// This method allows adding one or multiple form control items to the form, enabling dynamic construction and + /// management of form elements. It appends the specified controls to the form's content, making it flexible for + /// runtime modifications. + /// Example usage: + /// + /// var form = new FormControl(); + /// var textBox = new ControlFormItemInputTextBox { Name = "TextBox1", Label = "Enter Text" }; + /// var checkBox = new ControlFormItem { Name = "CheckBox1", Label = "Accept Terms" }; + /// form.Add(textBox, checkBox); + /// + /// This method accepts any item that derives from . + /// + void Add(params ControlFormItem[] item); -// /// -// /// Removes a form control item from the form. -// /// -// /// The form item. -// void Remove(ControlFormItem formItem); + /// + /// Removes a form control item from the form. + /// + /// The form item. + void Remove(ControlFormItem formItem); -// /// -// /// Validates the input elements for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// /// True if all form items are valid, false otherwise. -// bool Validate(RenderContextForm context); -// } -//} + /// + /// Validates the input elements for correctness of the data. + /// + /// The render context in which the inputs are validated. + /// True if all form items are valid, false otherwise. + bool Validate(IRenderControlFormContext renderContext); + } +} diff --git a/src/WebExpress.WebUI/WebControl/IFormValidation.cs b/src/WebExpress.WebUI/WebControl/IFormValidation.cs index 6e9165b6..fba2cce5 100644 --- a/src/WebExpress.WebUI/WebControl/IFormValidation.cs +++ b/src/WebExpress.WebUI/WebControl/IFormValidation.cs @@ -1,28 +1,31 @@ -ο»Ώ//using System.Collections.Generic; +ο»Ώusing System.Collections.Generic; -//namespace WebExpress.WebUI.WebControl -//{ -// public interface IFormValidation -// { -// /// -// /// Returns or sets whether the form element has been validated. -// /// -// //bool IsValidated { get; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Interface for form validation, providing methods and properties to validate form inputs. + /// + public interface IFormValidation + { + /// + /// Returns or sets whether the form element has been validated. + /// + //bool IsValidated { get; } -// /// -// /// Determines whether the inputs are valid. -// /// -// ICollection ValidationResults { get; } + /// + /// Determines whether the inputs are valid. + /// + ICollection ValidationResults { get; } -// /// -// /// Returns the most serious validation result. -// /// -// TypesInputValidity ValidationResult { get; } + /// + /// Returns the most serious validation result. + /// + TypesInputValidity ValidationResult { get; } -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// void Validate(RenderContextForm context); -// } -//} + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + void Validate(IRenderControlFormContext renderContext); + } +} diff --git a/src/WebExpress.WebUI/WebControl/IRenderControlFormContext.cs b/src/WebExpress.WebUI/WebControl/IRenderControlFormContext.cs new file mode 100644 index 00000000..5c97d09f --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/IRenderControlFormContext.cs @@ -0,0 +1,21 @@ +ο»Ώusing System.Collections.Generic; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Interface for rendering control form context, extending the base control context interface. + /// + public interface IRenderControlFormContext : IRenderControlContext + { + /// + /// Returns the form in which the control is rendered. + /// + public IControlForm Form { get; } + + /// + /// Returns the validation errors. + /// + public IEnumerable ValidationResults { get; } + } +} diff --git a/src/WebExpress.WebUI/WebControl/IRenderControlFormGroupContext.cs b/src/WebExpress.WebUI/WebControl/IRenderControlFormGroupContext.cs new file mode 100644 index 00000000..ed4a38b1 --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/IRenderControlFormGroupContext.cs @@ -0,0 +1,13 @@ +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Interface for rendering control form group context. + /// + public interface IRenderControlFormGroupContext : IRenderControlFormContext + { + /// + /// Returns the group of form items associated with the control. + /// + public ControlFormItemGroup Group { get; } + } +} diff --git a/src/WebExpress.WebUI/WebControl/RenderContextForm.cs b/src/WebExpress.WebUI/WebControl/RenderContextForm.cs deleted file mode 100644 index dea117da..00000000 --- a/src/WebExpress.WebUI/WebControl/RenderContextForm.cs +++ /dev/null @@ -1,71 +0,0 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebMessage; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class RenderContextForm : RenderContext -// { -// /// -// /// The form in which the control is rendered. -// /// -// public IControlForm Form { get; private set; } - -// /// -// /// Returns or sets the links to the java script files to be used. -// /// -// public IDictionary Scripts { get; } = new Dictionary(); - -// /// -// /// Returns the validation errors. -// /// -// public ICollection ValidationResults { get; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The page where the control is rendered. -// /// The request. -// /// The visual tree. -// /// The form in which the control is rendered. -// public RenderContextForm(IPage page, Request request, IVisualTree visualTree, IControlForm form) -// //: base(page, request, visualTree) -// { -// Form = form; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The context in which the control is rendered. -// /// The form in which the control is rendered. -// public RenderContextForm(RenderContext context, IControlForm form) -// : base(context) -// { -// Form = form; -// } - -// /// -// /// Copy-Constructor -// /// -// /// The render context to copy./param> -// public RenderContextForm(RenderContextForm context) -// : this(context, context?.Form) -// { -// Scripts = context.Scripts; -// } - -// /// -// /// Adds or replaces a java script if it exists. -// /// -// /// The key. -// /// The java script code. -// public void AddScript(string key, string code) -// { -// if (!Scripts.ContainsKey(key)) -// { -// Scripts.Add(key, code); -// } -// } -// } -//} diff --git a/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs b/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs deleted file mode 100644 index 67d5312f..00000000 --- a/src/WebExpress.WebUI/WebControl/RenderContextFormGroup.cs +++ /dev/null @@ -1,34 +0,0 @@ -ο»Ώ//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class RenderContextFormGroup : RenderContextForm -// { -// /// -// /// Die Gruppe, indem das Steuerelement gerendert wird -// /// -// public ControlFormItemGroup Group { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The context in which the control is rendered. -// /// The form in which the control is rendered. -// /// Die Gruppe -// public RenderContextFormGroup(RenderContext context, ControlForm form, ControlFormItemGroup group) -// : base(context, form) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The context in which the control is rendered. -// /// Die Gruppe -// public RenderContextFormGroup(RenderContextForm context, ControlFormItemGroup group) -// : base(context) -// { -// Group = group; -// } -// } -//} diff --git a/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs new file mode 100644 index 00000000..60f28f8d --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs @@ -0,0 +1,58 @@ +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Provides the context for rendering a form control within a web page. + /// + public class RenderControlFormContext : RenderControlContext, IRenderControlFormContext + { + private readonly IList _validationResults = []; + + /// + /// The form in which the control is rendered. + /// + public IControlForm Form { get; private set; } + + /// + /// Returns the validation errors. + /// + public IEnumerable ValidationResults => _validationResults; + + /// + /// Initializes a new instance of the class. + /// + /// The page context where the control is rendered. + /// The request. + /// The form in which the control is rendered. + public RenderControlFormContext(IPageContext pageContext, Request request, IControlForm form) + : base(pageContext, request) + { + Form = form; + } + + /// + /// Initializes a new instance of the class. + /// + /// The context in which the control is rendered. + /// The form in which the control is rendered. + public RenderControlFormContext(IRenderContext renderContext, IControlForm form) + : base(renderContext) + { + Form = form; + } + + /// + /// Copy-Constructor + /// + /// The render context to copy./param> + public RenderControlFormContext(IRenderControlFormContext context) + : this(context, context?.Form) + { + //AddScripts(context.Scripts); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs b/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs new file mode 100644 index 00000000..1e1a3664 --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs @@ -0,0 +1,24 @@ +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Provides the context for rendering a form control within a group on a web page. + /// + public class RenderControlFormGroupContext : RenderControlFormContext, IRenderControlFormGroupContext + { + /// + /// Die Gruppe, indem das Steuerelement gerendert wird + /// + public ControlFormItemGroup Group { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The context in which the control is rendered. + /// Die Gruppe + public RenderControlFormGroupContext(IRenderControlFormContext context, ControlFormItemGroup group) + : base(context) + { + Group = group; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs index 54d139fa..0261d058 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationEventArgs.cs @@ -1,27 +1,27 @@ -ο»Ώ//using System.Collections.Generic; +ο»Ώusing System.Collections.Generic; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Event argument for validating form inputs. -// /// -// public class ValidationEventArgs : FormEventArgs -// { -// /// -// /// Returns or sets the value to be checked. -// /// -// public string Value { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Event argument for validating form inputs. + /// + public class ValidationEventArgs : FormEventArgs + { + /// + /// Returns or sets the value to be checked. + /// + public string Value { get; set; } -// /// -// /// Returns or sets the validation results. -// /// -// public List Results { get; } = new List(); + /// + /// Returns or sets the validation results. + /// + public List Results { get; } = new List(); -// /// -// /// Initializes a new instance of the class. -// /// -// public ValidationEventArgs() -// { -// } -// } -//} + /// + /// Initializes a new instance of the class. + /// + public ValidationEventArgs() + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ValidationResult.cs b/src/WebExpress.WebUI/WebControl/ValidationResult.cs index ddf9384f..bfb3b8ad 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationResult.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationResult.cs @@ -1,26 +1,28 @@ -ο»Ώnamespace WebExpress.WebUI.WebControl -{ - public class ValidationResult - { - /// - /// Returns or sets the type. des Fehlers - /// - public TypesInputValidity Type { get; private set; } - - /// - /// Liefert oder setzt den Fehlertext - /// - public string Text { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// Der Fehlertyp - /// Der Fehlertext - public ValidationResult(TypesInputValidity type, string text) - { - Type = type; - Text = text; - } - } -} +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Represents the result of a validation process. + /// + public class ValidationResult + { + /// + /// Returns the type of the validation result. + /// + public TypesInputValidity Type { get; private set; } + + /// + /// Returns the error text. + /// + public string Text { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The type of the validation result. + /// The error text. + public ValidationResult(TypesInputValidity type, string text) + { + Type = type; + Text = text; + } } +} diff --git a/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs b/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs index 2b25a87a..dfdec76e 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationResultEventArgs.cs @@ -28,7 +28,7 @@ public ValidationResultEventArgs() /// /// Initializes a new instance of the class. /// - /// true if validation is successful, false otherwise. + /// True if validation is successful, false otherwise. public ValidationResultEventArgs(bool valid) { Valid = valid; From b686efa15edd40dbb61ac21857ab9fc06ce3f870 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Mon, 23 Dec 2024 23:37:39 +0100 Subject: [PATCH 22/59] refactoring and add tests --- .../Fixture/AssertExtensions.cs | 17 +- .../TestFragmentControlModalForm.cs | 23 + .../TestSectionFragmentControlModalForm.cs | 11 + .../WebControl/UnitTestControlControlHtml.cs | 55 +++ .../WebControl/UnitTestControlModalForm.cs | 175 ++----- .../WebControl/UnitTestControlPanelCard.cs | 143 ++++++ .../WebFragment/UnitTestFragmentManager.cs | 1 + .../WebControl/ControlForm.cs | 65 ++- .../WebControl/ControlHtml.cs | 91 ++-- .../WebControl/ControlModal.cs | 81 ++-- .../WebControl/ControlModalForm.cs | 448 +++++++++--------- .../WebControl/ControlPanel.cs | 10 +- .../WebControl/ControlPanelCard.cs | 261 +++++----- .../WebFragment/FragmentControlModalForm.cs | 61 +-- 14 files changed, 821 insertions(+), 621 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlModalForm.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlModalForm.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs diff --git a/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs index 2bea175b..9c1753d8 100644 --- a/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs +++ b/src/WebExpress.WebUI.Test/Fixture/AssertExtensions.cs @@ -23,7 +23,7 @@ public static partial class AssertExtensions /// The actual string to compare. public static void EqualWithPlaceholders(string expected, string actual) { - var str = RemoveLineBreaks(actual?.ToString() ?? "null"); + var str = RemoveLineBreaks(actual?.ToString()); Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); } @@ -35,7 +35,7 @@ public static void EqualWithPlaceholders(string expected, string actual) /// The actual string to compare. public static void EqualWithPlaceholders(string expected, IHtmlNode actual) { - var str = RemoveLineBreaks(actual?.ToString() ?? "null"); + var str = RemoveLineBreaks(actual?.ToString()); Assert.True(AreEqualWithPlaceholders(expected, str), $"Expected: {expected}{Environment.NewLine}Actual: {str}"); } @@ -47,6 +47,19 @@ public static void EqualWithPlaceholders(string expected, IHtmlNode actual) /// True if the actual string matches the expected string with placeholders; otherwise, false. private static bool AreEqualWithPlaceholders(string expected, string actual) { + if (expected == null && actual == null) + { + return true; + } + else if (expected != null && actual == null) + { + return false; + } + else if (expected == null && actual != null) + { + return false; + } + var pattern = "^" + Regex.Escape(expected).Replace(@"\*", ".*") + "$"; return Regex.IsMatch(actual, pattern); diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlModalForm.cs b/src/WebExpress.WebUI.Test/TestFragmentControlModalForm.cs new file mode 100644 index 00000000..65920e37 --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlModalForm.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlModalForm : FragmentControlModalForm + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlModalForm(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Add(new ControlText() { Text = "FragmentControlModalForm" }); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlModalForm.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlModalForm.cs new file mode 100644 index 00000000..d1a31fde --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlModalForm.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlModalForm : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs new file mode 100644 index 00000000..ff781da3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs @@ -0,0 +1,55 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the HTML control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlHtml + { + /// + /// Tests the id property of the HTML control. + /// + [Theory] + [InlineData(null, null)] + [InlineData("id", null)] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlHtml(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the html property of the HTML control. + /// + [Theory] + [InlineData(null, null)] + [InlineData("
                                                                                                                                      abc
                                                                                                                                      ", @"
                                                                                                                                      abc
                                                                                                                                      ")] + public void Html(string rawHtml, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlHtml() + { + Html = rawHtml + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs index 2511cf7f..9d295498 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs @@ -1,155 +1,76 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; -using Xunit.Abstractions; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.Test.WebControl { /// - /// Tests the modal form control. + /// Tests the modal control. /// [Collection("NonParallelTests")] - public class UnitTestControlModalForm : IClassFixture + public class UnitTestControlModalForm { /// - /// Returns the log. + /// Tests the id property of the modal control. /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlModalForm(UnitTestControlFixture fixture, ITestOutputHelper output) + [Theory] + [InlineData(null, @"*")] + [InlineData("id", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void Id(string id, string expected) { - Fixture = fixture; - Output = output; - } + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlModalForm(id) + { + }; - /// - /// Tests a empty form. - /// - [Fact] - public void EmptyForm() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlModalForm(); - - //var html = control.Render(context); - //var str = html.ToString(); + // test execution + var html = control.Render(context); - //// test execution - //Assert.StartsWith("
                                                                                                                                      *
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      *

                                                                                                                                      abc

                                                                                                                                      *
                                                                                                                                      ")] - /// - /// Tests a simple form with header. - /// - [Fact] - public void EmptyFormWithHeaderAtInstancing() + public void Header(string header, string expected) { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlModalForm("form", "header"); - - //var html = control.Render(context); - - //// test execution - //Assert.Contains(@"

                                                                                                                                      header

                                                                                                                                      ", html.Trim()); + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlModalForm() + { + Header = header + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); } /// - /// Tests a simple form with header. + /// Tests the add function of the modal control. /// [Fact] - public void EmptyFormWithHeaderAtProperty() + public void Add() { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlModalForm("form") { Header = "header" }; - - //var html = control.Render(context); - - //// test execution - //Assert.Contains(@"

                                                                                                                                      header

                                                                                                                                      ", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added during rendering. - /// - [Fact] - public void SimpleFormAtRender() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlModalForm(); - //var item = new ControlFormItemInputTextBox() { }; - - //// test execution - //var html = control.Render(context, [item]); - ////var str = html.ToString(); - - //Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added when instantiating. - /// - [Fact] - public void SimpleFormAtInstancing() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var item = new ControlFormItemInputTextBox() { }; - //var control = new ControlModalForm("form", item); - - //// test execution - //var html = control.Render(context); - - //Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added using add. - /// - [Fact] - public void SimpleFormAtAdd() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var item = new ControlFormItemInputTextBox() { }; - //var control = new ControlModalForm("form"); - - //control.Add(item); - - //// test execution - //var html = control.Render(context); - - //Assert.Contains(@"", html.Trim()); + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlModalForm() + { + }; + + // test execution + control.Add(new ControlFormItemInputTextBox() { Value = "abc" }); + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                      **
                                                                                                                                      ", html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs new file mode 100644 index 00000000..02e7958a --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs @@ -0,0 +1,143 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel card control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelCard + { + /// + /// Tests the id property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the header property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("header", @"
                                                                                                                                      header
                                                                                                                                      *
                                                                                                                                      ")] + public void Header(string header, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard() + { + Header = header + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the header image property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("headerImage", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void HeaderImage(string headerImage, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard() + { + HeaderImage = headerImage + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the headline property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("headline", @"
                                                                                                                                      *

                                                                                                                                      headline

                                                                                                                                      *
                                                                                                                                      ")] + public void Headline(string headline, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard() + { + Headline = headline + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the footer property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("footer", @"
                                                                                                                                      *
                                                                                                                                      footer
                                                                                                                                      ")] + public void Footer(string footer, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard() + { + Footer = footer + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the footer image property of the panel card control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("footerImage", @"
                                                                                                                                      *
                                                                                                                                      ")] + public void FooterImage(string footerImage, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCard() + { + FooterImage = footerImage + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index df9c368d..ff97f986 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -50,6 +50,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelTool), typeof(IScope), @"
                                                                                                                                      *
                                                                                                                                      TestFragmentControlPanelTool
                                                                                                                                      ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlSplitButtonItemLink), typeof(IScope), @"TestFragmentControlSplitButtonItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlTree), typeof(IScope), @"
                                                                                                                                      ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlModalForm), typeof(IScope), @"
                                                                                                                                      *Close
                                                                                                                                      *")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { // preconditions diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index d7c14087..029b8c85 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -464,13 +464,61 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable return form; } + /// + /// Adds one or more form items to the content of the form. + /// + /// The form items to add to the form. + /// + /// This method allows adding one or multiple form items to the collection of + /// the form. It is useful for dynamically constructing the user interface by appending + /// various controls to the form's content. + /// Example usage: + /// + /// var form = new ControlForm(); + /// var button1 = new ControlButton { Text = "Save" }; + /// var button2 = new ControlButton { Text = "Cancel" }; + /// form.Add(button1, button2); + /// + /// This method accepts any control that implements the interface. + /// + public void Add(params ControlFormItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds one or more form items to the content of the form. + /// + /// The form items to add to the form. + /// + /// This method allows adding one or multiple form items to the collection of + /// the form. It is useful for dynamically constructing the user interface by appending + /// various controls to the form's content. + /// Example usage: + /// + /// var form = new ControlForm(); + /// var button1 = new ControlButton { Text = "Save" }; + /// var button2 = new ControlButton { Text = "Cancel" }; + /// form.Add(button1, button2); + /// + /// This method accepts any control that implements the interface. + /// + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + /// - /// Adds a form control. + /// Removes a form item from the content of the form. /// - /// The form item. - public void Add(params ControlFormItem[] item) + /// The form item to remove from the form. + /// + /// This method allows removing a specific form item from the collection of + /// the form. + /// + public virtual void Remove(ControlFormItem item) { - _items.AddRange(item); + _items.Remove(item); } /// @@ -527,15 +575,6 @@ public void AddSecondaryButton(params ControlFormItemButton[] buttons) _secondaryButtons.AddRange(buttons); } - /// - /// Removes a form control item from the form. - /// - /// The form item. - public void Remove(ControlFormItem formItem) - { - _items.Remove(formItem); - } - /// /// Removes a form control button from the form. /// diff --git a/src/WebExpress.WebUI/WebControl/ControlHtml.cs b/src/WebExpress.WebUI/WebControl/ControlHtml.cs index e6111c79..f8480ea9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlHtml.cs +++ b/src/WebExpress.WebUI/WebControl/ControlHtml.cs @@ -1,58 +1,41 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlHtml : Control -// { -// /// -// /// Retruns or sets the html source code. -// /// -// public string Html { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents an HTML control that can render raw HTML content. + /// + public class ControlHtml : Control + { + /// + /// Retruns or sets the html source code. + /// + public string Html { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlHtml(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The text. + public ControlHtml(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlHtml(string id, int value) -// : base(id) -// { -// Html = value.ToString(); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlRaw + { + Html = Html + }; -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlRaw -// { -// Html = Html -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index 850a20ca..60f38e15 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -11,10 +11,12 @@ namespace WebExpress.WebUI.WebControl /// public class ControlModal : Control { + private readonly List _content = []; + /// - /// Returns or sets the content. + /// Returns the content. /// - public IEnumerable Content { get; private set; } = []; + public IEnumerable Content => _content; /// /// Returns or sets whether the fader effect should be used. @@ -45,44 +47,69 @@ public class ControlModal : Control /// Initializes a new instance of the class. /// /// The id of the control. - public ControlModal(string id = null) + /// The text. + /// The content of the html element. + public ControlModal(string id = null, params IControl[] content) : base(id) { + _content.AddRange(content); } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The headline. - public ControlModal(string id, string header) - : this(id) + /// + /// Adds one or more controls to the content of the modal. + /// + /// The controls to add to the modal. + /// + /// This method allows adding one or multiple controls to the collection of + /// the modal. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var modal = new ControlModal(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// modal.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) { - Header = header; + _content.AddRange(controls); } - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The headline. - /// The content of the html element. - public ControlModal(string id, string header, params Control[] content) - : this(id, header) + /// + /// Adds one or more controls to the content of the modal. + /// + /// The controls to add to the v. + /// + /// This method allows adding one or multiple controls to the collection of + /// the modal. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var modal = new ControlModal(); + /// var text1 = new ControlText { Text = "Save" }; + /// var text2 = new ControlText { Text = "Cancel" }; + /// modal.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) { - Content = content ?? []; + _content.AddRange(controls); } /// - /// Initializes a new instance of the class. + /// Removes a control from the content of the modal. /// - /// The id of the control. - /// The text. - /// The content of the html element. - public ControlModal(string id = null, params Control[] content) - : this(id, string.Empty) + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the modal. + /// + public virtual void Remove(Control control) { - Content = content ?? []; + _content.Remove(control); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs index 05efe6c4..f9d8c866 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs @@ -1,220 +1,228 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlModalForm : ControlModal -// { -// /// -// /// Returns the form. -// /// -// public ControlForm Form { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlModalForm(string id = null) -// : this(id, string.Empty, null) -// { - -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The headline. -// public ControlModalForm(string id, string header) -// : this(id, header, null) -// { - -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The form controls. -// public ControlModalForm(string id, params ControlFormItem[] content) -// : this(id, string.Empty, content) -// { - -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The headline. -// /// The form controls. -// public ControlModalForm(string id, string header, params ControlFormItem[] content) -// : base("modal_" + id, string.Empty, null) -// { -// Form = content != null ? new ControlForm(id, content) : new ControlForm(id); -// Form.InitializeForm += OnInitializeForm; -// Form.Validated += OnValidatedForm; -// Header = header; -// } - -// /// -// /// Adds a form control. -// /// -// /// The form item. -// public void Add(params ControlFormItem[] item) -// { -// Form.Add(item); -// } - -// /// -// /// Removes a form control. -// /// -// /// The form item. -// public void Remove(ControlFormItem item) -// { -// Form.Remove(item); -// } - -// /// -// /// Invoked when the form is initialized. -// /// -// /// The sender. -// /// The event argument. -// private void OnInitializeForm(object sender, FormEventArgs e) -// { -// ShowIfCreated = false; -// } - -// /// -// /// Invoked when the form has been validated. -// /// -// /// The sender. -// /// The event argument. -// private void OnValidatedForm(object sender, ValidationResultEventArgs e) -// { -// if (!e.Valid) -// { -// ShowIfCreated = true; -// Fade = false; -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return Render(context, Form.Items); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The form items. -// /// The control as html. -// public virtual IHtmlNode Render(IRenderContext context, IEnumerable items) -// { -// var fade = Fade; -// var classes = Classes.ToList(); - -// var form = Form.Render(context, items) as HtmlElementFormForm; - -// classes.Add("modal"); - -// if (Fade) -// { -// classes.Add("fade"); -// } - -// var headerText = new HtmlElementSectionH4(I18N.Translate(context.Culture, Header)) -// { -// Class = "modal-title" -// }; - -// var headerButton = new HtmlElementFieldButton() -// { -// Class = "btn-close" -// }; -// headerButton.AddUserAttribute("aria-label", "close"); -// headerButton.AddUserAttribute("data-bs-dismiss", "modal"); - -// var header = new HtmlElementTextContentDiv(headerText, headerButton) -// { -// Class = "modal-header" -// }; - -// var formElements = form.Elements.Where(x => !(x is HtmlElementSectionFooter)); - -// var body = new HtmlElementTextContentDiv(formElements) -// { -// Class = "modal-body" -// }; - -// var footer = default(HtmlElementTextContentDiv); - -// var submitFooterButton = new ControlFormItemButton(); - -// var cancelFooterButton = new ControlButtonLink() -// { -// Text = I18N.Translate(context.Culture, "webexpress.webui:modal.close.label") -// }.Render(context) as HtmlElement; - -// cancelFooterButton.AddUserAttribute("data-bs-dismiss", "modal"); - -// footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderContextForm(context, Form)), cancelFooterButton) -// { -// Class = "modal-footer d-flex justify-content-between" -// }; - -// var content = new HtmlElementTextContentDiv(header, body, footer) -// { -// Class = "modal-content" -// }; - -// var dialog = new HtmlElementTextContentDiv(content) -// { -// Class = "modal-dialog", -// Role = "document" -// }; - -// var html = new HtmlElementTextContentDiv(dialog) -// { -// Id = Id, -// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = "dialog" -// }; - -// if (!string.IsNullOrWhiteSpace(OnShownCode)) -// { -// var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; -// context.VisualTree.AddScript(Id + "_shown", shown); -// } - -// if (!string.IsNullOrWhiteSpace(OnHiddenCode)) -// { -// var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; -// context.VisualTree.AddScript(Id + "_hidden", hidden); -// } - -// if (ShowIfCreated) -// { -// var show = "$('#" + Id + "').modal('show');"; -// context.VisualTree.AddScript(Id + "_showifcreated", show); -// } - -// form.Elements.Clear(); -// form.Elements.Add(html); - -// Fade = fade; - -// return form; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a modal form control that can display a form in a modal dialog. + /// + public class ControlModalForm : ControlModal + { + /// + /// Returns the form. + /// + public ControlForm Form { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The form controls. + public ControlModalForm(string id = null, params ControlFormItem[] items) + : base("modal_" + id) + { + Form = items != null ? new ControlForm(id, items) : new ControlForm(id); + Form.InitializeForm += OnInitializeForm; + Form.Validated += OnValidatedForm; + } + + /// + /// Adds one or more form items to the content of the form. + /// + /// The form items to add to the form. + /// + /// This method allows adding one or multiple form items to the collection of + /// the form. It is useful for dynamically constructing the user interface by appending + /// various controls to the form's content. + /// Example usage: + /// + /// var form = new ControlForm(); + /// var button1 = new ControlButton { Text = "Save" }; + /// var button2 = new ControlButton { Text = "Cancel" }; + /// form.Add(button1, button2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params ControlFormItem[] items) + { + Form.Add(items); + } + + /// + /// Adds one or more form items to the content of the form. + /// + /// The form items to add to the form. + /// + /// This method allows adding one or multiple form items to the collection of + /// the form. It is useful for dynamically constructing the user interface by appending + /// various controls to the form's content. + /// Example usage: + /// + /// var form = new ControlForm(); + /// var button1 = new ControlButton { Text = "Save" }; + /// var button2 = new ControlButton { Text = "Cancel" }; + /// form.Add(button1, button2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable items) + { + Form.Add(items); + } + + /// + /// Removes a form item from the content of the form. + /// + /// The form item to remove from the form. + /// + /// This method allows removing a specific form item from the collection of + /// the form. + /// + public virtual void Remove(ControlFormItem item) + { + Form.Remove(item); + } + + /// + /// Invoked when the form is initialized. + /// + /// The sender. + /// The event argument. + private void OnInitializeForm(object sender, FormEventArgs e) + { + ShowIfCreated = false; + } + + /// + /// Invoked when the form has been validated. + /// + /// The sender. + /// The event argument. + private void OnValidatedForm(object sender, ValidationResultEventArgs e) + { + if (!e.Valid) + { + ShowIfCreated = true; + Fade = false; + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return Render(renderContext, Form.Items); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// The form items. + /// An HTML node representing the rendered control. + public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + { + var fade = Fade; + var classes = Classes.ToList(); + + var form = Form.Render(renderContext, items) as HtmlElementFormForm; + + classes.Add("modal"); + + if (Fade) + { + classes.Add("fade"); + } + + var headerText = new HtmlElementSectionH4(I18N.Translate(renderContext.Request?.Culture, Header)) + { + Class = "modal-title" + }; + + var headerButton = new HtmlElementFieldButton() + { + Class = "btn-close" + }; + headerButton.AddUserAttribute("aria-label", "close"); + headerButton.AddUserAttribute("data-bs-dismiss", "modal"); + + var header = new HtmlElementTextContentDiv(headerText, headerButton) + { + Class = "modal-header" + }; + + var formElements = form.Elements.Where(x => !(x is HtmlElementSectionFooter)); + + var body = new HtmlElementTextContentDiv(formElements.ToArray()) + { + Class = "modal-body" + }; + + var footer = default(HtmlElementTextContentDiv); + + var submitFooterButton = new ControlFormItemButton(); + + var cancelFooterButton = new ControlButtonLink() + { + Text = I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:modal.close.label") + }.Render(renderContext) as HtmlElement; + + cancelFooterButton.AddUserAttribute("data-bs-dismiss", "modal"); + + footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderControlFormContext(renderContext, Form)), cancelFooterButton) + { + Class = "modal-footer d-flex justify-content-between" + }; + + var content = new HtmlElementTextContentDiv(header, body, footer) + { + Class = "modal-content" + }; + + var dialog = new HtmlElementTextContentDiv(content) + { + Class = "modal-dialog", + Role = "document" + }; + + var html = new HtmlElementTextContentDiv(dialog) + { + Id = Id, + Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = "dialog" + }; + + if (!string.IsNullOrWhiteSpace(OnShownCode)) + { + var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; + renderContext.AddScript(Id + "_shown", shown); + } + + if (!string.IsNullOrWhiteSpace(OnHiddenCode)) + { + var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; + renderContext.AddScript(Id + "_hidden", hidden); + } + + if (ShowIfCreated) + { + var show = "$('#" + Id + "').modal('show');"; + renderContext.AddScript(Id + "_showifcreated", show); + } + + form.Clear(); + form.Add(html); + + Fade = fade; + + return form; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 3557b902..a7dcaa72 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -61,8 +61,8 @@ public ControlPanel(string id = null, params IControl[] children) /// Example usage: /// /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "Save" }; - /// var text2 = new ControlText { Text = "Cancel" }; + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; /// panel.Add(text1, text2); /// /// This method accepts any control that implements the interface. @@ -83,8 +83,8 @@ public virtual void Add(params IControl[] controls) /// Example usage: /// /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "Save" }; - /// var text2 = new ControlText { Text = "Cancel" }; + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; /// panel.Add(new List([text1, text2])); /// /// This method accepts any control that implements the interface. @@ -102,7 +102,7 @@ public virtual void Add(IEnumerable controls) /// This method allows removing a specific control from the collection of /// the control panel. /// - public void Remove(Control control) + public virtual void Remove(Control control) { _content.Remove(control); } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs index 11786942..f24f86a7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs @@ -1,144 +1,117 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Box with frame. -// /// -// public class ControlPanelCard : ControlPanel -// { -// /// -// /// Returns or sets the header text. -// /// -// public string Header { get; set; } - -// /// -// /// Returns or sets the header image. -// /// -// public string HeaderImage { get; set; } - -// /// -// /// Returns or sets the headline. -// /// -// public string Headline { get; set; } - -// /// -// /// Returns or sets the footer. -// /// -// public string Footer { get; set; } - -// /// -// /// Returns or sets the footer image. -// /// -// public string FooterImage { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelCard(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelCard(string id, params Control[] items) -// : base(id, items) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The controls to insert. -// public ControlPanelCard(params Control[] items) -// : base(items) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Border = new PropertyBorder(true); -// } - -// /// -// /// Adds controls to the panel. -// /// -// /// The controls to insert. -// public void Add(params Control[] items) -// { -// Content.AddRange(items); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("card", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// if (!string.IsNullOrWhiteSpace(Header)) -// { -// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(I18N.Translate(Header))) { Class = "card-header" }); -// } - -// if (!string.IsNullOrWhiteSpace(HeaderImage)) -// { -// html.Elements.Add(new HtmlElementMultimediaImg() -// { -// Src = HeaderImage, -// Class = "card-img-top" -// }); -// } - -// if (!string.IsNullOrWhiteSpace(Headline)) -// { -// Content.Insert(0, new ControlText() -// { -// Text = I18N.Translate(Headline), -// Classes = new List(["card-title"]), -// Format = TypeFormatText.H4 -// }); -// } - -// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "card-text" }) { Class = "card-body" }); - -// if (!string.IsNullOrWhiteSpace(FooterImage)) -// { -// html.Elements.Add(new HtmlElementMultimediaImg() -// { -// Src = FooterImage, -// Class = "card-img-top" -// }); -// } - -// if (!string.IsNullOrWhiteSpace(Footer)) -// { -// html.Elements.Add(new HtmlElementTextContentDiv(new HtmlText(Footer)) { Class = "card-footer" }); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel card with a header, footer, and content area. + /// + public class ControlPanelCard : ControlPanel + { + /// + /// Returns or sets the header text. + /// + public string Header { get; set; } + + /// + /// Returns or sets the header image. + /// + public string HeaderImage { get; set; } + + /// + /// Returns or sets the headline. + /// + public string Headline { get; set; } + + /// + /// Returns or sets the footer. + /// + public string Footer { get; set; } + + /// + /// Returns or sets the footer image. + /// + public string FooterImage { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel card. + public ControlPanelCard(string id = null, params IControl[] controls) + : base(id, controls) + { + Border = new PropertyBorder(true); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var content = Content; + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("card", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + if (!string.IsNullOrWhiteSpace(Header)) + { + html.Add(new HtmlElementTextContentDiv(new HtmlText(I18N.Translate(Header))) { Class = "card-header" }); + } + + if (!string.IsNullOrWhiteSpace(HeaderImage)) + { + html.Add(new HtmlElementMultimediaImg() + { + Src = HeaderImage, + Class = "card-img-top" + }); + } + + if (!string.IsNullOrWhiteSpace(Headline)) + { + var headContent = (IEnumerable)[new ControlText() + { + Text = I18N.Translate(Headline), + Classes = new List(["card-title"]), + Format = TypeFormatText.H4 + }]; + + content = headContent.Concat(Content); + } + + html.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(content.Select(x => x.Render(renderContext)).ToArray()) + { + Class = "card-text" + }) + { + Class = "card-body" + }); + + if (!string.IsNullOrWhiteSpace(FooterImage)) + { + html.Add(new HtmlElementMultimediaImg() + { + Src = FooterImage, + Class = "card-img-top" + }); + } + + if (!string.IsNullOrWhiteSpace(Footer)) + { + html.Add(new HtmlElementTextContentDiv(new HtmlText(Footer)) { Class = "card-footer" }); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs index d8bd6b6c..eb406e92 100644 --- a/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlModalForm.cs @@ -1,32 +1,35 @@ -ο»Ώ//using WebExpress.WebCore.WebPage; -//using WebExpress.WebUI.WebControl; +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; -//namespace WebExpress.WebUI.WebFragment -//{ -// public class FragmentControlModalForm : ControlModalForm, IFragment -// { -// /// -// /// Returns the context of the fragment. -// /// -// public IFragmentContext FragmentContext { get; private set; } +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a modal form control fragment that can display a form in a modal dialog. + /// + public class FragmentControlModalForm : ControlModalForm, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the fragment or null. -// public FragmentControlModalForm(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlModalForm(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } -// /// -// /// Initialization -// /// -// /// The context. -// /// The page where the fragment is active. -// public virtual void Initialization(IFragmentContext context, IPage page) -// { -// FragmentContext = context; -// } -// } -//} + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} From 141d8d083895568031c1f93a24b5a63375ddd475 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Tue, 24 Dec 2024 13:16:51 +0100 Subject: [PATCH 23/59] refactoring and add tests --- .../WebControl/UnitTestControlDropdown.cs | 18 +- .../WebControl/UnitTestControlLinkList.cs | 158 ++++++++ .../WebControl/UnitTestControlListItemLink.cs | 210 +++++++++++ .../WebControl/ControlLinkList.cs | 197 ++++++---- .../WebControl/ControlListItem.cs | 66 +++- .../WebControl/ControlListItemLink.cs | 343 ++++++++---------- src/WebExpress.WebUI/WebControl/IControl.cs | 77 +++- 7 files changed, 787 insertions(+), 282 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs index 3f9b514b..71f550fe 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs @@ -55,7 +55,7 @@ public void BackgroundColor(TypeColorButton backgroundColor, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -78,7 +78,7 @@ public void Size(TypeSizeButton size, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -101,7 +101,7 @@ public void Outline(bool outline, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -123,7 +123,7 @@ public void Block(TypeBlockButton block, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -145,7 +145,7 @@ public void Toogle(TypeToggleDropdown toogle, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -168,7 +168,7 @@ public void Text(string text, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -191,7 +191,7 @@ public void Tooltip(string tooltip, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -236,7 +236,7 @@ public void Icon(TypeIcon icon, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -259,7 +259,7 @@ public void Active(TypeActive active, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs new file mode 100644 index 00000000..c4d7a4b7 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs @@ -0,0 +1,158 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the link list control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlLinkList + { + /// + /// Tests the id property of the link list control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the link list control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                                                                      WebExpress.WebUI
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList() + { + Name = name, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name color property of the link list control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                      abc
                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                      abc
                                                                                                                                      ")] + public void NameColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList() + { + Name = "abc", + NameColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the link list control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                      ")] + [InlineData(TypeIcon.Star, @"
                                                                                                                                      ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the link list control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Info, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.White, @"
                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the link list control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLinkList(); + + // test execution + control.Add(new ControlLink() { Text = "abc" }); + + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs new file mode 100644 index 00000000..1908f1f1 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs @@ -0,0 +1,210 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the list item link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlListItemLink + { + /// + /// Tests the id property of the list item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the list item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the list item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title property of the list item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the target property of the list item link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tooltip property of the list item link control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + [InlineData("a
                                                                                                                                      b", @"")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the list item link control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the list item link control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlListItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlListItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlListItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlListItemLink(null); + var control5 = new ControlListItemLink(null); + var control6 = new ControlListItemLink(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html1); + AssertExtensions.EqualWithPlaceholders(@"", html2); + AssertExtensions.EqualWithPlaceholders(@"", html3); + AssertExtensions.EqualWithPlaceholders(@"", html4); + AssertExtensions.EqualWithPlaceholders(@"", html5); + AssertExtensions.EqualWithPlaceholders(@"", html6); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs index 1b062b9b..157a43ce 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs @@ -1,78 +1,139 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Display a list of links. -// /// -// public class ControlLinkList : Control -// { -// /// -// /// Returns or sets the text.farbe des Namens -// /// -// public PropertyColorText NameColor { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control that displays a list of links with optional icons and names. + /// + public class ControlLinkList : Control + { + private readonly List _links = []; -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } + /// + /// Returns or sets the links. + /// + public IEnumerable Links => _links; -// /// -// /// Returns or sets the name. -// /// -// public string Name { get; set; } + /// + /// Returns or sets the color of the name text. + /// + public PropertyColorText NameColor { get; set; } -// /// -// /// Returns or sets the links. -// /// -// public List Links { get; } = new List(); + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlLinkList(string id = null) -// : base(id) -// { -// } + /// + /// Returns or sets the name. + /// + public string Name { get; set; } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var icon = new HtmlElementTextSemanticsSpan() -// { -// Class = Icon?.ToClass() -// }; + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The links to add to the control. + public ControlLinkList(string id = null, params IControlLink[] links) + : base(id) + { + _links.AddRange(links); + } -// var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Name))) -// { -// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", -// Class = NameColor?.ToClass() -// }; + /// + /// Adds one or more links to the content of the link list control. + /// + /// The links to add to the content. + /// + /// This method allows adding one or multiple links to the collection of + /// the link list control. It is useful for dynamically constructing the user interface by appending + /// various links to the link list content. + /// Example usage: + /// + /// var list = new ControlLinkList(); + /// var link1 = new ControlLink { Text = "A" }; + /// var link2 = new ControlLink { Text = "B" }; + /// list.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControlLink[] links) + { + _links.AddRange(links); + } -// var html = new HtmlElementTextContentDiv -// ( -// Icon != null && Icon.HasIcon ? icon : null, -// Name != null ? name : null -// ) -// { -// Id = Id, -// Class = GetClasses(), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; + /// + /// Adds one or more links to the content of the link list control. + /// + /// The links to add to the content. + /// + /// This method allows adding one or multiple links to the collection of + /// the link list control. It is useful for dynamically constructing the user interface by appending + /// various links to the link list content. + /// Example usage: + /// + /// var list = new ControlLinkList(); + /// var link1 = new ControlLink { Text = "A" }; + /// var link2 = new ControlLink { Text = "B" }; + /// list.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable links) + { + _links.AddRange(links); + } -// html.Elements.AddRange(Links?.Select(x => x.Render(context))); + /// + /// Removes a link from the content of the link list control. + /// + /// The link to remove from the content. + /// + /// This method allows removing a specific link from the collection of + /// the link list control. + /// + public virtual void Remove(IControlLink link) + { + _links.Remove(link); + } -// return html; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var icon = new HtmlElementTextSemanticsSpan() + { + Class = Icon?.ToClass() + }; + + var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Name))) + { + Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", + Class = NameColor?.ToClass() + }; + + var html = new HtmlElementTextContentDiv + ( + Icon != null && Icon.HasIcon ? icon : null, + Name != null ? name : null + ) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + + html.Add(Links?.Select(x => x.Render(renderContext))); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index a4b3bf8e..74da07d9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -10,10 +10,12 @@ namespace WebExpress.WebUI.WebControl ///
                                                                                                                                      public class ControlListItem : Control { + private readonly List _content = []; + /// - /// Returns or sets the content. + /// Returns the content. /// - public IEnumerable Content { get; private set; } + public IEnumerable Content => _content; /// /// Returns or sets the ativity state of the list item. @@ -31,18 +33,64 @@ public TypeActive Active public ControlListItem(string id = null, params Control[] content) : base(id) { - Content = content ?? []; + _content.AddRange(content); + } + + /// + /// Adds one or more controls to the content of the list item. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the list item. It is useful for dynamically constructing the user interface by appending + /// various controls to the content. + /// Example usage: + /// + /// var item = new ControlListItem(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// item.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content of the list item. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the list item. It is useful for dynamically constructing the user interface by appending + /// various controls to the content. + /// Example usage: + /// + /// var item = new ControlListItem(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// item.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _content.AddRange(controls); } /// - /// Initializes a new instance of the class. + /// Removes a control from the content of the list item. /// - /// The id of the control. - /// The content of the html element. - public ControlListItem(string id = null, IEnumerable content = null) - : base(id) + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the list item. + /// + public virtual void Remove(Control control) { - Content = content ?? []; + _content.Remove(control); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs index 19d3b132..866dc7e5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs @@ -1,195 +1,148 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebMessage; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlListItemLink : ControlListItem -// { -// /// -// /// Returns or sets the target uri. -// /// -// public Uri Uri { get; set; } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the target. -// /// -// public TypeTarget Target { get; set; } - -// /// -// /// Returns or sets the tooltip. -// /// -// public string Title { get; set; } - -// /// -// /// Returns or sets a tooltip text. -// /// -// public string Tooltip { get; set; } - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Returns or sets the parameters that apply to the link. -// /// -// public List Params { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlListItemLink(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlListItemLink(string id, params Control[] content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlListItemLink(params Control[] content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlListItemLink(string id, List content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlListItemLink(List content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Returns all local and temporary parameters. -// /// -// /// The context in which the control is rendered. -// /// The parameters. -// public string GetParams(IPage page) -// { -// var dict = new Dictionary(); - -// // copying the parameters of the link -// if (Params != null) -// { -// foreach (var v in Params) -// { -// if (v.Scope == ParameterScope.Parameter) -// { -// if (!dict.ContainsKey(v.Key.ToLower())) -// { -// dict.Add(v.Key.ToLower(), v); -// } -// else -// { -// dict[v.Key.ToLower()] = v; -// } -// } -// } -// } - -// return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var param = ""; // GetParams(context?.Page); - -// var html = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = Css.Concatenate("list-group-item-action", GetClasses()), -// Style = GetStyles(), -// Role = Role, -// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), -// Target = Target, -// Title = Title, -// OnClick = OnClick?.ToString() -// }; - -// if (Icon != null && Icon.HasIcon) -// { -// html.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// html.Elements.Add(new HtmlText(Text)); -// } - -// //if (Modal != null) -// //{ -// // html.AddUserAttribute("data-bs-toggle", "modal"); -// // html.AddUserAttribute("data-bs-target", "#" + Modal.Id); - -// // return new HtmlList(html, Modal.Render(context)); -// //} - -// if (!string.IsNullOrWhiteSpace(Tooltip)) -// { -// html.AddUserAttribute("data-bs-toggle", "tooltip"); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a list item link control that can contain other controls as its content. + /// + public class ControlListItemLink : ControlListItem + { + /// + /// Returns or sets the target uri. + /// + public string Uri { get; set; } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the target. + /// + public TypeTarget Target { get; set; } + + /// + /// Returns or sets the tooltip. + /// + public string Title { get; set; } + + /// + /// Returns or sets a tooltip text. + /// + public string Tooltip { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the parameters that apply to the link. + /// + public List Params { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlListItemLink(string id = null, params Control[] content) + : base(id, content) + { + } + + /// + /// Returns all local and temporary parameters. + /// + /// The parameters. + public string GetParams() + { + var dict = new Dictionary(); + + // copying the parameters of the link + if (Params != null) + { + foreach (var v in Params) + { + if (v.Scope == ParameterScope.Parameter) + { + if (!dict.ContainsKey(v.Key.ToLower())) + { + dict.Add(v.Key.ToLower(), v); + } + else + { + dict[v.Key.ToLower()] = v; + } + } + } + } + + return string.Join("&", dict.Where(x => !string.IsNullOrWhiteSpace(x.Value.Value)).Select(x => x.Value.ToString())); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var param = GetParams(); + + var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = Css.Concatenate("list-group-item-action", GetClasses()), + Style = GetStyles(), + Role = Role, + Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), + Target = Target, + Title = Title, + OnClick = OnClick?.ToString() + }; + + if (Icon != null && Icon.HasIcon) + { + html.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + html.Add(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))); + } + + //if (Modal != null) + //{ + // html.AddUserAttribute("data-bs-toggle", "modal"); + // html.AddUserAttribute("data-bs-target", "#" + Modal.Id); + + // return new HtmlList(html, Modal.Render(context)); + //} + + if (!string.IsNullOrWhiteSpace(Tooltip)) + { + html.AddUserAttribute("data-bs-toggle", "tooltip"); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/IControl.cs b/src/WebExpress.WebUI/WebControl/IControl.cs index 133f6ae3..67ff5fea 100644 --- a/src/WebExpress.WebUI/WebControl/IControl.cs +++ b/src/WebExpress.WebUI/WebControl/IControl.cs @@ -1,4 +1,5 @@ -ο»Ώusing WebExpress.WebCore.WebHtml; +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl @@ -13,6 +14,80 @@ public interface IControl /// string Id { get; } + /// + /// Returns or sets the horizontal alignment. + /// + TypeHorizontalAlignment HorizontalAlignment { get; set; } + + /// + /// Returns or sets the text color. + /// + PropertyColorText TextColor { get; set; } + + /// + /// Returns or sets the background color. + /// + PropertyColorBackground BackgroundColor { get; set; } + + /// + /// Returns or sets the border color. + /// + PropertyColorBorder BorderColor { get; set; } + + /// + /// Returns or sets the padding. + /// + PropertySpacingPadding Padding { get; set; } + + /// + /// Returns or sets the margin. + /// + PropertySpacingMargin Margin { get; set; } + + /// + /// Returns or sets the border. + /// + PropertyBorder Border { get; set; } + + /// + /// Returns or sets the column property if the control is on a grid. + /// + PropertyGrid GridColumn { get; set; } + + /// + /// Returns or sets the width property of the control. + /// + TypeWidth Width { get; set; } + + /// + /// Returns or sets the height property of the control. + /// + TypeHeight Height { get; set; } + + /// + /// Returns or sets the css class. + /// + List Classes { get; set; } + + /// Returns or sets the css style. + /// + List Styles { get; set; } + + /// + /// Returns or sets the role. + /// + string Role { get; set; } + + /// + /// Returns or sets the OnClick attribute, which executes a java script on the client. + /// + PropertyOnClick OnClick { get; set; } + + /// + /// Determines whether the control is active and rendering. + /// + bool Enable { get; set; } + /// /// Convert the control to HTML. /// From edebd2de2cb53a2db7611be0bacfc8f15725a377 Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Wed, 25 Dec 2024 13:12:02 +0100 Subject: [PATCH 24/59] refactoring and add tests --- .../UnitTestControlFormItemPanel.cs | 108 +++++ .../WebControl/UnitTestControlPanel.cs | 8 +- .../WebControl/UnitTestControlTreeItemLink.cs | 210 +++++++++ .../ControlFormItemInputCheckbox.cs | 87 ---- .../WebControl/ControlFormItemPanel.cs | 203 +++++--- .../WebControl/ControlPanel.cs | 6 +- .../WebControl/ControlTreeItemLink.cs | 432 ++++++++---------- src/WebExpress.WebUI/WebExpress.WebUI.csproj | 11 +- 8 files changed, 658 insertions(+), 407 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs delete mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs new file mode 100644 index 00000000..b2dedae7 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs @@ -0,0 +1,108 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form panel control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemPanel + { + /// + /// Tests the id property of the form panel control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPanel(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the form panel control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPanel() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the form panel control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPanel() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the form panel control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlFormItemPanel(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs index 0ee9a52d..e07b9376 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -52,7 +52,7 @@ public void Direction(TypeDirection direction, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -75,7 +75,7 @@ public void Fluid(TypePanelContainer fluid, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -98,7 +98,7 @@ public void Add(Type child, string expected) var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs new file mode 100644 index 00000000..2f23c73b --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs @@ -0,0 +1,210 @@ +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the tree item link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTreeItemLink + { + /// + /// Tests the id property of the tree item link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                    • ")] + [InlineData("id", @"
                                                                                                                                    • ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the tree item link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                    • ")] + [InlineData("abc", @"
                                                                                                                                    • abc
                                                                                                                                    • ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                    • webexpress.webui:plugin.name
                                                                                                                                    • ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the tree item link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                    • ")] + [InlineData("/a", @"
                                                                                                                                    • ")] + [InlineData("/a/b", @"
                                                                                                                                    • ")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title property of the tree item link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                    • ")] + [InlineData("a", @"
                                                                                                                                    • ")] + [InlineData("b", @"
                                                                                                                                    • ")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the target property of the tree item link control. + /// + [Theory] + [InlineData(TypeTarget.None, @"
                                                                                                                                    • ")] + [InlineData(TypeTarget.Blank, @"
                                                                                                                                    • ")] + [InlineData(TypeTarget.Self, @"
                                                                                                                                    • ")] + [InlineData(TypeTarget.Parent, @"
                                                                                                                                    • ")] + [InlineData(TypeTarget.Framename, @"
                                                                                                                                    • ")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tooltip property of the tree item link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                    • ")] + [InlineData("a", @"
                                                                                                                                    • ")] + [InlineData("b", @"
                                                                                                                                    • ")] + [InlineData("a
                                                                                                                                      b", @"
                                                                                                                                    • ")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Tooltip = tooltip + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the tree item link control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                    • ")] + [InlineData(TypeIcon.Star, @"
                                                                                                                                    • ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTreeItemLink() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the tree item link control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlTreeItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlTreeItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlTreeItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlTreeItemLink(null); + var control5 = new ControlTreeItemLink(null); + var control6 = new ControlTreeItemLink(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html1); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html2); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html3); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html4); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html5); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                    • ", html6); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs deleted file mode 100644 index 1337b072..00000000 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs +++ /dev/null @@ -1,87 +0,0 @@ -ο»Ώ//using System; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.Internationalization; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputCheckBox : ControlFormItemInput -// { -// /// -// /// Returns or sets whether the checkbox should be displayed on a new line. -// /// -// public bool Inline { get; set; } - -// /// -// /// Returns or sets the description. -// /// -// public string Description { get; set; } - -// /// -// /// Returns or sets a search pattern that checks the content. -// /// -// public string Pattern { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// public ControlFormItemInputCheckBox(string id = null) -// : base(id) -// { -// Value = "false"; -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// var value = context.Request.GetParameter(Name)?.Value; - -// Value = string.IsNullOrWhiteSpace(value) || !value.Equals("on", StringComparison.OrdinalIgnoreCase) ? "false" : "true"; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var html = new HtmlElementTextContentDiv -// ( -// new HtmlElementFieldLabel -// ( -// new HtmlElementFieldInput() -// { -// Name = Name, -// Pattern = Pattern, -// Type = "checkbox", -// Disabled = Disabled, -// //Role = Role, -// Checked = Value.Equals("true") -// }, -// new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + I18N.Translate(Description)) -// ) -// { -// } -// ) -// { -// Class = Css.Concatenate("checkbox", GetClasses()), -// Style = GetStyles(), -// }; - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } -// } -//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs index 674d83d9..3b6eb246 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs @@ -1,75 +1,142 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemPanel : ControlFormItem -// { -// /// -// /// Returns or sets the content. -// /// -// public IEnumerable Content { get; private set; } = new List(); +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a panel control that can contain multiple form items. + /// + public class ControlFormItemPanel : ControlFormItem + { + private readonly List _content = []; -// /// -// /// Returns or sets the arrangement of the content. -// /// -// public TypeDirection Direction -// { -// get => (TypeDirection)GetProperty(TypeDirection.Default); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns the content of the form panel. + /// + /// + /// The content property holds a collection of controls that represent the visual and interactive elements + /// within this container. + /// + public IEnumerable Content => _content; -// /// -// /// Fixed or full-width adjustment. -// /// -// public TypePanelContainer Fluid -// { -// get => (TypePanelContainer)GetProperty(TypePanelContainer.None); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the arrangement of the content. + /// + public TypeDirection Direction + { + get => (TypeDirection)GetProperty(TypeDirection.Default); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemPanel(string id) -// : base(id) -// { -// } + /// + /// Fixed or full-width adjustment. + /// + public TypePanelContainer Fluid + { + get => (TypePanelContainer)GetProperty(TypePanelContainer.None); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlFormItemPanel(string id, IEnumerable content) -// : base(id) -// { -// Content = content; -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemPanel(string id) + : base(id) + { + } -// /// -// /// Initialization -// /// -// public override void Initialize(RenderContextForm context) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlFormItemPanel(string id = null, params IControl[] controls) + : base(id) + { + _content.AddRange(controls.Where(x => x != null)); + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// return new HtmlElementTextContentDiv(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = GetClasses(), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; -// } -// } -//} + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlFormItemPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlFormItemPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _content.AddRange(controls); + } + + /// + /// Removes a control from the content of the control panel. + /// + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the control panel. + /// + public virtual void Remove(Control control) + { + _content.Remove(control); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index a7dcaa72..ff843800 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -43,11 +43,11 @@ public TypePanelContainer Fluid /// Initializes a new instance of the class. ///
                                                                                                                                      /// The id of the control. - /// The child controls to be added to the panel. - public ControlPanel(string id = null, params IControl[] children) + /// The child controls to be added to the panel. + public ControlPanel(string id = null, params IControl[] controls) : base(id) { - _content.AddRange(children.Where(x => x != null)); + _content.AddRange(controls.Where(x => x != null)); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs index b43f9a0e..02c7dc51 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs @@ -1,240 +1,192 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebMessage; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlTreeItemLink : ControlTreeItem -// { -// /// -// /// Returns or sets the target uri. -// /// -// public string Uri { get; set; } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the target. -// /// -// public TypeTarget Target { get; set; } - -// /// -// /// Returns or sets the tooltip. -// /// -// public string Title { get; set; } - -// /// -// /// Returns or sets a tooltip text. -// /// -// public string Tooltip { get; set; } - -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } - -// /// -// /// Liefert oder setzt die für den Link gültigen Parameter -// /// -// public List Params { get; set; } - - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTreeItemLink(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTreeItemLink(string id, params Control[] content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlTreeItemLink(params Control[] content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTreeItemLink(string id, List content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlTreeItemLink(List content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Returns all local and temporary parameters. -// /// -// /// The context in which the control is rendered. -// /// The parameters. -// public string GetParams(IPage page) -// { -// var dict = new Dictionary(); - -// // Übernahme der Parameter des Link -// if (Params != null) -// { -// foreach (var v in Params) -// { -// if (string.IsNullOrWhiteSpace(Uri?.ToString())) -// { -// if (!dict.ContainsKey(v.Key.ToLower())) -// { -// dict.Add(v.Key.ToLower(), v); -// } -// else -// { -// dict[v.Key.ToLower()] = v; -// } -// } -// } -// } - -// return string.Join("&", from x in dict where !string.IsNullOrWhiteSpace(x.Value.Value) select x.Value.ToString()); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var param = ""; // GetParams(context?.Page); - -// var link = new HtmlElementTextSemanticsA(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = Css.Concatenate("link tree-link", Active == TypeActive.Active ? "tree-link-active" : ""), -// Role = Role, -// Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), -// Target = Target, -// Title = Title, -// OnClick = OnClick?.ToString() -// }; - -// if (Icon != null && Icon.HasIcon) -// { -// link.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// link.Elements.Add(new HtmlText(Text)); -// } - -// if (!string.IsNullOrWhiteSpace(Tooltip)) -// { -// link.AddUserAttribute("data-toggle", "tooltip"); -// } - -// var expander = new HtmlElementTextSemanticsSpan -// { -// Class = Css.Concatenate("tree-treeview-expander", Children.Count > 0 ? "tree-treeview-angle" : "tree-treeview-dot") -// }; - -// if (Children.Count > 0 && Expand != TypeExpandTree.Collapse) -// { -// expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); -// } -// var container = new HtmlElementTextContentDiv(expander, link) -// { -// Class = Css.Concatenate("tree-treeview-container") -// }; - -// var html = new HtmlElementTextContentLi(Layout == TypeLayoutTreeItem.TreeView ? container : link) -// { -// Id = Id, -// Class = Css.Concatenate(Layout switch -// { -// TypeLayoutTreeItem.Group => "list-group-item-action", -// TypeLayoutTreeItem.Flush => "list-group-item-action", -// TypeLayoutTreeItem.Horizontal => "list-group-item-action", -// TypeLayoutTreeItem.TreeView => "tree-item", -// _ => "" -// }, Active.ToClass()), -// Style = GetStyles(), -// Role = Role -// }; - -// if (Children.Count > 0) -// { -// var items = (from x in Children select x.Render(context)).ToList(); -// var ul = new HtmlElementTextContentUl(items) -// { -// Class = Css.Concatenate(Layout switch -// { -// TypeLayoutTreeItem.TreeView => "tree-treeview-node", -// TypeLayoutTreeItem.Simple => "tree-simple-node", -// _ => Layout.ToClass() -// }, Expand.ToClass()) -// }; - -// switch (Layout) -// { -// case TypeLayoutTreeItem.Horizontal: -// case TypeLayoutTreeItem.Flush: -// case TypeLayoutTreeItem.Group: -// items.ForEach(x => x.AddClass("list-group-item")); -// break; -// } - -// html.Elements.Add(ul); -// } - -// return html; -// } -// } -//} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebMessage; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a tree item link control that can contain other controls and tree items. + /// + public class ControlTreeItemLink : ControlTreeItem + { + /// + /// Returns or sets the target uri. + /// + public string Uri { get; set; } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the target. + /// + public TypeTarget Target { get; set; } + + /// + /// Returns or sets the tooltip. + /// + public string Title { get; set; } + + /// + /// Returns or sets a tooltip text. + /// + public string Tooltip { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the parameters for the control. + /// + public List Params { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlTreeItemLink(string id = null, params Control[] content) + : base(id, content) + { + } + + /// + /// Returns all local and temporary parameters. + /// + /// The parameters. + public string GetParams() + { + var dict = new Dictionary(); + + // Übernahme der Parameter des Link + if (Params != null) + { + foreach (var v in Params) + { + if (string.IsNullOrWhiteSpace(Uri?.ToString())) + { + if (!dict.ContainsKey(v.Key.ToLower())) + { + dict.Add(v.Key.ToLower(), v); + } + else + { + dict[v.Key.ToLower()] = v; + } + } + } + } + + return string.Join("&", dict.Where(x => !string.IsNullOrWhiteSpace(x.Value.Value)).Select(x => x.Value.ToString())); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var param = GetParams(); + + var link = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = Css.Concatenate("link tree-link", Active == TypeActive.Active ? "tree-link-active" : ""), + Role = Role, + Href = Uri?.ToString() + (param.Length > 0 ? "?" + param : string.Empty), + Target = Target, + Title = Title, + OnClick = OnClick?.ToString() + }; + + if (Icon != null && Icon.HasIcon) + { + link.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + link.Add(new HtmlText(Text)); + } + + if (!string.IsNullOrWhiteSpace(Tooltip)) + { + link.AddUserAttribute("data-toggle", "tooltip"); + } + + var expander = new HtmlElementTextSemanticsSpan + { + Class = Css.Concatenate("tree-treeview-expander", Children.Count() > 0 ? "tree-treeview-angle" : "tree-treeview-dot") + }; + + if (Children.Count() > 0 && Expand != TypeExpandTree.Collapse) + { + expander.Class = Css.Concatenate("tree-treeview-angle-down", expander.Class); + } + var container = new HtmlElementTextContentDiv(expander, link) + { + Class = Css.Concatenate("tree-treeview-container") + }; + + var html = new HtmlElementTextContentLi(Layout == TypeLayoutTreeItem.TreeView ? container : link) + { + Id = Id, + Class = Css.Concatenate(Layout switch + { + TypeLayoutTreeItem.Group => "list-group-item-action", + TypeLayoutTreeItem.Flush => "list-group-item-action", + TypeLayoutTreeItem.Horizontal => "list-group-item-action", + TypeLayoutTreeItem.TreeView => "tree-item", + _ => "" + }, Active.ToClass()), + Style = GetStyles(), + Role = Role + }; + + if (Children.Count() > 0) + { + var items = (from x in Children select x.Render(renderContext)).ToList(); + var ul = new HtmlElementTextContentUl(items.ToArray()) + { + Class = Css.Concatenate(Layout switch + { + TypeLayoutTreeItem.TreeView => "tree-treeview-node", + TypeLayoutTreeItem.Simple => "tree-simple-node", + _ => Layout.ToClass() + }, Expand.ToClass()) + }; + + switch (Layout) + { + case TypeLayoutTreeItem.Horizontal: + case TypeLayoutTreeItem.Flush: + case TypeLayoutTreeItem.Group: + items.ForEach(x => x.AddClass("list-group-item")); + break; + } + + html.Add(ul); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index 194d7020..d9080054 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -27,8 +27,14 @@ + + + + + + @@ -394,9 +400,4 @@ - - - - - From 98e4dbe18a43e87702196c08ca49b1501e395927 Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Wed, 25 Dec 2024 13:28:05 +0100 Subject: [PATCH 25/59] refactoring and add tests --- .../UnitTestControlFormItemInputCheckbox.cs | 103 ++++++++++++++ .../ControlFormItemInputCheckbox.cs | 96 +++++++++++++ .../ControlFormItemInputComboBox.cs | 128 ------------------ .../ControlFormItemInputComboBoxItem.cs | 52 ------- 4 files changed, 199 insertions(+), 180 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs create mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs delete mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs delete mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs new file mode 100644 index 00000000..c2455ef0 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs @@ -0,0 +1,103 @@ +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item input checkbox control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputCheckbox + { + /// + /// Tests the id property of the form item input checkbox control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCheckbox(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Inline property of the form item input checkbox control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                      ")] + [InlineData(true, @"
                                                                                                                                      ")] + public void Inline(bool inline, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCheckbox + { + Inline = inline + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Description property of the form item input checkbox control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("description", @"
                                                                                                                                      ")] + public void Description(string description, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCheckbox + { + Description = description + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Pattern property of the form item input checkbox control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("pattern", @"
                                                                                                                                      ")] + public void Pattern(string pattern, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCheckbox + { + Pattern = pattern + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs new file mode 100644 index 00000000..4c9190ab --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs @@ -0,0 +1,96 @@ +ο»Ώusing System; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a checkbox input form item control. + /// + public class ControlFormItemInputCheckbox : ControlFormItemInput + { + /// + /// Returns or sets whether the checkbox should be displayed on a new line. + /// + public bool Inline { get; set; } + + /// + /// Returns or sets the description. + /// + public string Description { get; set; } + + /// + /// Returns or sets a search pattern that checks the content. + /// + public string Pattern { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id. + public ControlFormItemInputCheckbox(string id = null) + : base(id) + { + Value = "false"; + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + var value = renderContext.Request.GetParameter(Name)?.Value; + + Value = string.IsNullOrWhiteSpace(value) || !value.Equals("on", StringComparison.OrdinalIgnoreCase) ? "false" : "true"; + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var html = new HtmlElementTextContentDiv + ( + new HtmlElementFieldLabel + ( + new HtmlElementFieldInput() + { + Name = Name, + Pattern = Pattern, + Type = "checkbox", + Disabled = Disabled, + //Role = Role, + Checked = Value.Equals("true") + }, + new HtmlText + ( + string.IsNullOrWhiteSpace(Description) ? + string.Empty : + " " + I18N.Translate(renderContext.Request?.Culture, Description) + ) + ) + { + } + ) + { + Id = Id, + Class = Css.Concatenate("checkbox", GetClasses()), + Style = GetStyles(), + }; + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs deleted file mode 100644 index ad0dcc49..00000000 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBox.cs +++ /dev/null @@ -1,128 +0,0 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputComboBox : ControlFormItemInput -// { -// /// -// /// Returns or sets the entries. -// /// -// public List Items { get; private set; } = new List(); - -// ///// -// ///// Returns or sets the selected item. -// ///// -// //public string Selected { get; set; } - -// /// -// /// Returns or sets the OnChange attribute. -// /// -// public PropertyOnChange OnChange { get; set; } - -// ///// -// ///// Returns or sets the selected item. anhand des Wertes -// ///// -// //public string SelectedValue { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputComboBox(string id = null) -// : base(id) -// { -// Name = id; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The ComboBox entries. -// public ControlFormItemInputComboBox(string id, params string[] items) -// : this(id) -// { -// Items.AddRange(from v in items select new ControlFormItemInputComboBoxItem() { Text = v }); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The ComboBox entries. -// public ControlFormItemInputComboBox(string id, params ControlFormItemInputComboBoxItem[] items) -// : this(id) -// { -// Items.AddRange(items); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The ComboBox entries. -// public ControlFormItemInputComboBox(string id, string name, IEnumerable items) -// : this(id, name) -// { -// Items.AddRange(items); -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// Value = context.Request.GetParameter(Name)?.Value; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var html = new HtmlElementFieldSelect() -// { -// Id = Id, -// Name = Name, -// Class = Css.Concatenate("form-select", GetClasses()), -// Style = GetStyles(), -// Role = Role, -// Disabled = Disabled, -// OnChange = OnChange?.ToString() -// }; - -// foreach (var v in Items) -// { -// if (v.SubItems.Count > 0) -// { -// html.Elements.Add(new HtmlElementFormOptgroup() { Label = v.Text }); -// foreach (var s in v.SubItems) -// { -// html.Elements.Add(new HtmlElementFormOption() { Value = s.Value, Text = I18N.Translate(context.Culture, s.Text), Selected = (s.Value == Value) }); -// } -// } -// else -// { -// html.Elements.Add(new HtmlElementFormOption() { Value = v.Value, Text = I18N.Translate(context.Culture, v.Text), Selected = (v.Value == Value) }); -// } -// } - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } -// } -//} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs deleted file mode 100644 index 8b3903d3..00000000 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboBoxItem.cs +++ /dev/null @@ -1,52 +0,0 @@ -ο»Ώ//using System.Collections.Generic; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputComboBoxItem -// { -// public List SubItems { get; private set; } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets a value. -// /// -// public string Value { get; set; } - -// /// -// /// Returns or sets a tag value. -// /// -// public object Tag { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// public ControlFormItemInputComboBoxItem() -// { -// SubItems = new List(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The child entries. -// public ControlFormItemInputComboBoxItem(params ControlFormItemInputComboBoxItem[] subitems) -// : this() -// { -// SubItems.AddRange(subitems); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The child entries. -// public ControlFormItemInputComboBoxItem(IEnumerable subitems) -// : this() -// { -// SubItems.AddRange(subitems); -// } -// } -//} From bbc2d08e154b9d9606111dd898496548651e2c23 Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Wed, 25 Dec 2024 14:16:24 +0100 Subject: [PATCH 26/59] refactoring and add tests --- .../UnitTestControlFormItemInputCombobox.cs | 189 ++++++++++ .../WebControl/ControlFormItemInput.cs | 327 ++++++++++-------- .../ControlFormItemInputCombobox.cs | 104 ++++++ .../ControlFormItemInputComboboxItem.cs | 51 +++ 4 files changed, 527 insertions(+), 144 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs create mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs create mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemInputComboboxItem.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs new file mode 100644 index 00000000..f314f105 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs @@ -0,0 +1,189 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item input combobox control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputCombobox + { + /// + /// Tests the id property of the form item input combobox control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Icon property of the form item input combobox control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Label property of the form item input combobox control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("label", @"")] + public void Label(string label, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox + { + Label = label + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the help property of the form item input combobox control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("help", @"")] + public void Help(string help, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox + { + Help = help + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the disabled property of the form item input combobox control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void Disabled(bool disabled, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox + { + Disabled = disabled + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the prepend property of the form item input combobox control. + /// + [Fact] + public void Prepend() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox(); + control.Prepend.Add(new ControlText { Text = "prepend" }); + + // test execution + var html = control.Render(context); + + var expected = @""; + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the append property of the form item input combobox control. + /// + [Fact] + public void Append() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox(); + control.Append.Add(new ControlText { Text = "append" }); + + // test execution + var html = control.Render(context); + + var expected = @""; + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tag property of the form item input combobox control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("tag", @"")] + public void Tag(object tag, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputCombobox + { + Tag = tag + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs index 650b267f..041f0b14 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs @@ -1,144 +1,183 @@ -ο»Ώusing System; -using System.Collections.Generic; -using System.Linq; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Identifies a control that is to be filled in by the user. - /// - public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation - { - /// - /// Event to validate the input values. - /// - public event EventHandler Validation; - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the label. - /// - public string Label { get; set; } - - /// - /// Returns or sets an optional help text. - /// - public string Help { get; set; } - - /// - /// Returns or sets whether the input element is disabled. - /// - public bool Disabled { get; set; } - - /// - /// Returns or sets the elements that are displayed in front of the control. - /// - public List Prepend { get; private set; } - - /// - /// Returns or sets the elements that are displayed after the control. - /// - public List Append { get; private set; } - - /// - /// Returns or sets whether the form element has been validated. - /// - private bool IsValidated { get; set; } - - /// - /// Returns or sets an object that is linked to the control. - /// - public object Tag { get; set; } - - /// - /// Determines whether the inputs are valid. - /// - public virtual ICollection ValidationResults { get; } = new List(); - - /// - /// Returns the most serious validation result. - /// - public virtual TypesInputValidity ValidationResult - { - get - { - var buf = ValidationResults; - - if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) - { - return TypesInputValidity.Error; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) - { - return TypesInputValidity.Warning; - } - else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) - { - return TypesInputValidity.Success; - } - - return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; - } - } - - /// - /// Returns or sets the value. - /// - public virtual string Value { get; set; } = string.Empty; - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - public ControlFormItemInput(string id) - : base(id) - { - Prepend = new List(); - Append = new List(); - IsValidated = false; - } - - /// - /// Initializes the form emement. - /// - /// The context in which the control is rendered. - public override void Initialize(IRenderControlFormContext renderContext) - { - } - - /// - /// Raises the validation event. - /// - /// The event argument. - protected virtual void OnValidation(ValidationEventArgs e) - { - Validation?.Invoke(this, e); - } - - /// - /// Checks the input element for correctness of the data. - /// - /// The context in which the inputs are validated. - public virtual void Validate(IRenderControlFormContext renderContext) - { - IsValidated = true; - - if (ValidationResults is List validationResults) - { - validationResults.Clear(); - - if (!Disabled) - { - var args = new ValidationEventArgs() { Value = Value, Context = renderContext }; - OnValidation(args); - - validationResults.AddRange(args.Results); - } - } - } - } -} +ο»Ώusing System; +using System.Collections.Generic; +using System.Linq; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Identifies a control that is to be filled in by the user. + /// + /// + /// This class provides the base functionality for form input items. + /// + public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation + { + private readonly List _prepend = []; + private readonly List _append = []; + + /// + /// Event to validate the input values. + /// + public event EventHandler Validation; + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the label. + /// + public string Label { get; set; } + + /// + /// Returns or sets an optional help text. + /// + public string Help { get; set; } + + /// + /// Returns or sets whether the input element is disabled. + /// + public bool Disabled { get; set; } + + /// + /// Returns the elements that are displayed in front of the control. + /// + public List Prepend => _prepend; + + /// + /// Returns the elements that are displayed after the control. + /// + public List Append => _append; + + /// + /// Returns or sets whether the form element has been validated. + /// + private bool IsValidated { get; set; } + + /// + /// Returns or sets an object that is linked to the control. + /// + public object Tag { get; set; } + + /// + /// Determines whether the inputs are valid. + /// + public virtual ICollection ValidationResults { get; } = new List(); + + /// + /// Returns the most serious validation result. + /// + public virtual TypesInputValidity ValidationResult + { + get + { + var buf = ValidationResults; + + if (buf.Where(x => x.Type == TypesInputValidity.Error).Any()) + { + return TypesInputValidity.Error; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Warning).Any()) + { + return TypesInputValidity.Warning; + } + else if (buf.Where(x => x.Type == TypesInputValidity.Success).Any()) + { + return TypesInputValidity.Success; + } + + return IsValidated ? TypesInputValidity.Success : TypesInputValidity.Default; + } + } + + /// + /// Returns or sets the value. + /// + public virtual string Value { get; set; } = string.Empty; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInput(string id) + : base(id) + { + IsValidated = false; + } + + // + // Adds one or more controls to the prepend list. + // + // The controls to add. + public void AddPrepend(params IControl[] controls) + { + _prepend.AddRange(controls); + } + + /// + /// Removes a control from the prepend list. + /// + /// The control to remove. + public void RemovePrepend(IControl control) + { + _prepend.Remove(control); + } + + /// + /// Adds one or more controls to the append list. + /// + /// The controls to add. + public void AddAppend(params IControl[] controls) + { + _append.AddRange(controls); + } + /// + /// Removes a control from the append list. + /// + /// The control to remove. + public void RemoveAppend(IControl control) + { + _append.Remove(control); + } + + /// + /// Initializes the form emement. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } + + /// + /// Raises the validation event. + /// + /// The event argument. + protected virtual void OnValidation(ValidationEventArgs e) + { + Validation?.Invoke(this, e); + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public virtual void Validate(IRenderControlFormContext renderContext) + { + IsValidated = true; + + if (ValidationResults is List validationResults) + { + validationResults.Clear(); + + if (!Disabled) + { + var args = new ValidationEventArgs() { Value = Value, Context = renderContext }; + OnValidation(args); + + validationResults.AddRange(args.Results); + } + } + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs new file mode 100644 index 00000000..69f34d36 --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs @@ -0,0 +1,104 @@ +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a combobox input control within a form. + /// + /// + /// This control allows users to select an item from a dropdown list. + /// + public class ControlFormItemInputCombobox : ControlFormItemInput + { + private readonly List _items = []; + + /// + /// Returns the combobox items. + /// + public IEnumerable Items => _items; + + ///// + ///// Returns or sets the selected item. + ///// + //public string Selected { get; set; } + + /// + /// Returns or sets the OnChange attribute. + /// + public PropertyOnChange OnChange { get; set; } + + ///// + ///// Returns or sets the selected item. + ///// + //public string SelectedValue { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The ComboBox entries. + public ControlFormItemInputCombobox(string id = null, params ControlFormItemInputComboboxItem[] items) + : base(id) + { + _items.AddRange(items); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + Value = renderContext.Request.GetParameter(Name)?.Value; + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var html = new HtmlElementFieldSelect() + { + Id = Id, + Name = Name, + Class = Css.Concatenate("form-select", GetClasses()), + Style = GetStyles(), + Role = Role, + Disabled = Disabled, + OnChange = OnChange?.ToString() + }; + + foreach (var v in Items) + { + if (v.SubItems.Count() > 0) + { + html.Add(new HtmlElementFormOptgroup() { Label = v.Text }); + foreach (var s in v.SubItems) + { + html.Add(new HtmlElementFormOption() { Value = s.Value, Text = I18N.Translate(renderContext.Request?.Culture, s.Text), Selected = (s.Value == Value) }); + } + } + else + { + html.Add(new HtmlElementFormOption() { Value = v.Value, Text = I18N.Translate(renderContext.Request?.Culture, v.Text), Selected = (v.Value == Value) }); + } + } + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboboxItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboboxItem.cs new file mode 100644 index 00000000..1ff148d2 --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputComboboxItem.cs @@ -0,0 +1,51 @@ +ο»Ώusing System.Collections.Generic; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents an item in a combobox control within a form. + /// + public class ControlFormItemInputComboboxItem + { + private readonly List _subItems = []; + + /// + /// Returns the sub-items of the combobox item. + /// + public IEnumerable SubItems => _subItems; + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets a value. + /// + public string Value { get; set; } + + /// + /// Returns or sets a tag value. + /// + public object Tag { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The child entries. + public ControlFormItemInputComboboxItem(params ControlFormItemInputComboboxItem[] subitems) + { + _subItems.AddRange(subitems); + } + + /// + /// Initializes a new instance of the class. + /// + /// The child entries. + public ControlFormItemInputComboboxItem(IEnumerable subitems) + : this() + { + _subItems.AddRange(subitems); + } + } +} From 80fff9b36bfcd7e1ede52f999f93484060f7a0ed Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Wed, 25 Dec 2024 23:35:50 +0100 Subject: [PATCH 27/59] refactoring and add tests --- .../UnitTestControlDropdownItemHeader.cs | 2 +- .../UnitTestControlFormItemInputDatepicker.cs | 103 +++++ .../UnitTestControlFormItemInputFile.cs | 101 +++++ .../UnitTestControlFormItemInputGroup.cs | 80 ++++ .../UnitTestControlFormItemInputMove.cs | 102 +++++ .../UnitTestControlFormItemInputRadio.cs | 120 ++--- .../UnitTestControlFormItemInputSelection.cs | 171 +++++++ .../UnitTestControlFormItemPanel.cs | 2 +- .../UnitTestControlFormItemPrepend.cs | 108 +++++ .../UnitTestControlFormItemStaticText.cs | 103 +++++ .../WebControl/UnitTestControlList.cs | 28 ++ .../WebControl/UnitTestControlNavigation.cs | 104 +++++ .../UnitTestControlNavigationItemDropdown.cs | 306 +++++++++++++ .../UnitTestControlNavigationItemHeader.cs | 56 +++ .../WebControl/UnitTestControlPanelFooter.cs | 104 +++++ .../WebControl/UnitTestControlPanelMain.cs | 104 +++++ .../WebControl/UnitTestControlPanelSplit.cs | 109 +++++ .../WebAttribute/OptionAttribute.cs | 21 - .../WebControl/ControlFormItemGroup.cs | 37 +- .../WebControl/ControlFormItemInput.cs | 43 +- .../ControlFormItemInputCombobox.cs | 2 +- .../ControlFormItemInputDatepicker.cs | 258 +++++------ .../WebControl/ControlFormItemInputFile.cs | 244 +++++----- .../WebControl/ControlFormItemInputGroup.cs | 141 +++--- .../WebControl/ControlFormItemInputMove.cs | 310 +++++++------ .../WebControl/ControlFormItemInputRadio.cs | 251 +++++----- .../ControlFormItemInputSelection.cs | 334 +++++++------- .../ControlFormItemInputSelectionItem.cs | 87 ++-- .../WebControl/ControlFormItemInputTextBox.cs | 6 +- .../WebControl/ControlFormItemPrepend.cs | 98 ++-- .../WebControl/ControlFormItemStaticText.cs | 108 ++--- .../WebControl/ControlNavigation.cs | 428 +++++++++--------- .../ControlNavigationItemDropdown.cs | 54 ++- .../WebControl/ControlNavigationItemHeader.cs | 86 ++-- .../WebControl/ControlPanel.cs | 251 +++++----- .../WebControl/ControlPanelFooter.cs | 101 ++--- .../WebControl/ControlPanelMain.cs | 73 +-- .../WebControl/ControlPanelSplit.cs | 350 +++++++------- .../WebControl/IFormValidation.cs | 2 +- 39 files changed, 3313 insertions(+), 1675 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs delete mode 100644 src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs index f1acef47..1346a793 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs @@ -50,7 +50,7 @@ public void Text(string text, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs new file mode 100644 index 00000000..c039c8b1 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs @@ -0,0 +1,103 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form datepicker control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputDatepicker + { + /// + /// Tests the id property of the form datepicker control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputDatepicker(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form datepicker control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputDatepicker() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form datepicker control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("2023-10-10", @"")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputDatepicker() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the required property of the form datepicker control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void Required(bool required, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputDatepicker() + { + Required = required + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs new file mode 100644 index 00000000..97731ebc --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs @@ -0,0 +1,101 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form file input control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputFile + { + /// + /// Tests the id property of the form file input control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputFile(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form file input control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputFile() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the required property of the form file input control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void Required(bool required, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputFile() + { + Required = required + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the accept property of the form file input control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("image/*", @"")] + public void Accept(string accept, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputFile(); + + // test execution + control.AddAcceptFile(accept); + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs new file mode 100644 index 00000000..837e6b71 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs @@ -0,0 +1,80 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form group control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputGroup + { + /// + /// Tests the id property of the form label control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputGroup(id, new ControlFormItemGroupColumnVertical()) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form group control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputGroup(null, new ControlFormItemGroupColumnVertical()) + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form group control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputGroup(null, new ControlFormItemGroupColumnVertical()) + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs new file mode 100644 index 00000000..97aa977b --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs @@ -0,0 +1,102 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form move control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputMove + { + /// + /// Tests the id property of the form move control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputMove(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form move control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputMove() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form move control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputMove() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Add method of the form move control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputMove() + { + }; + + // test execution + control.Add(new ControlFormItemInputSelectionItem() { Label = "label" }); + var html = control.Render(context); + + Assert.NotEmpty(control.Options); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                      ", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs index b8194625..3a8464fc 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs @@ -1,97 +1,103 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; -using Xunit.Abstractions; +using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.Test.WebControl { /// - /// Tests the inline radio control. + /// Tests the form item input radio control. /// [Collection("NonParallelTests")] - public class UnitTestControlFormItemInputRadio : IClassFixture + public class UnitTestControlFormItemInputRadio { /// - /// Returns the log. + /// Tests the id property of the form item input radio control. /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlFormItemInputRadio(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - - /// - /// Tests a empty control. - /// - [Fact] - public void Empty() + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) { // preconditions - //var context = Fixture.CrerateContextForm(); - //var control = new ControlFormItemInputRadio(); + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputRadio(id) + { + }; - //var html = control.Render(context).Trim(); + // test execution + var html = control.Render(context); - //// test execution - //Assert.StartsWith(@"
                                                                                                                                      ", html); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// - /// Tests a control. + /// Tests the Inline property of the form item input radio control. /// - [Fact] - public void True() + [Theory] + [InlineData(false, @"
                                                                                                                                      ")] + [InlineData(true, @"
                                                                                                                                      ")] + public void Inline(bool inline, string expected) { // preconditions - //var context = Fixture.CrerateContextForm(); - //var control = new ControlFormItemInputRadio() { Checked = true }; + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputRadio + { + Inline = inline + }; - //var html = control.Render(context).Trim(); + // test execution + var html = control.Render(context); - //// test execution - //Assert.StartsWith(@"
                                                                                                                                      ", html); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// - /// Tests a control. + /// Tests the Description property of the form item input radio control. /// - [Fact] - public void False() + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("description", @"
                                                                                                                                      ")] + public void Description(string description, string expected) { // preconditions - //var context = Fixture.CrerateContextForm(); - //var control = new ControlFormItemInputRadio() { Checked = false }; + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputRadio + { + Description = description + }; - //var html = control.Render(context).Trim(); + // test execution + var html = control.Render(context); - //// test execution - //Assert.StartsWith(@"
                                                                                                                                      ", html); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// - /// Tests a control. + /// Tests the Pattern property of the form item input radio control. /// - [Fact] - public void Description() + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("pattern", @"
                                                                                                                                      ")] + public void Pattern(string pattern, string expected) { - //// preconditions - //var context = Fixture.CrerateContextForm(); - //var control = new ControlFormItemInputRadio() { Description = "abcdefg" }; + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputRadio + { + Pattern = pattern + }; - //var html = control.Render(context).Trim(); + // test execution + var html = control.Render(context); - //// test execution - //Assert.StartsWith(@"
                                                                                                                                      ", html); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs new file mode 100644 index 00000000..b111d988 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs @@ -0,0 +1,171 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form selection control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemInputSelection + { + /// + /// Tests the id property of the form selection control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form selection control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form selection control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                      ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the placeholder property of the form selection control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("Select an option", @"
                                                                                                                                      ")] + public void Placeholder(string placeholder, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + Placeholder = placeholder + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the HideDescription property of the form selection control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                      ")] + [InlineData(true, @"
                                                                                                                                      ")] + public void HideDescription(bool hideDescription, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + HideDescription = hideDescription + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the MultiSelect property of the form selection control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                      ")] + [InlineData(true, @"
                                                                                                                                      ")] + public void MultiSelect(bool multiSelect, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + MultiSelect = multiSelect + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the MultiSelect property of the form selection control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemInputSelection() + { + }; + + // test execution + control.Add(new ControlFormItemInputSelectionItem() { Label = "label" }); + var html = control.Render(context); + + Assert.NotEmpty(control.Options); + AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                      ", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs index b2dedae7..a3fc56cb 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs @@ -82,7 +82,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the form panel control. + /// Tests the add function of the form panel control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs new file mode 100644 index 00000000..e2cbf974 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs @@ -0,0 +1,108 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form item prepend control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemPrepend + { + /// + /// Tests the id property of the form item prepend control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPrepend(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the form item prepend control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPrepend() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the form item prepend control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemPrepend() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the form item prepend control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlFormItemPrepend(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs new file mode 100644 index 00000000..76048c14 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs @@ -0,0 +1,103 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form static text control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemStaticText + { + /// + /// Tests the id property of the form static text control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                      ")] + [InlineData("id", @"

                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemStaticText(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name property of the form static text control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                      ")] + [InlineData("abc", @"

                                                                                                                                      ")] + public void Name(string name, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemStaticText() + { + Name = name + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the label property of the form static text control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                      ")] + [InlineData("abc", @"

                                                                                                                                      ")] + public void Label(string label, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemStaticText() + { + Label = label + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form static text control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                      ")] + [InlineData("abc", @"

                                                                                                                                      abc

                                                                                                                                      ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var control = new ControlFormItemStaticText() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs index 8fefdb28..e9e31264 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs @@ -31,6 +31,34 @@ public void Id(string id, string expected) Assert.Equal(expected, html.Trim()); } + /// + /// Tests the background color property of the list control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                        ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                          ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                            ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                              ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                    ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlList() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + /// /// Tests the layout property of the list control. /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs new file mode 100644 index 00000000..adc0aced --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs @@ -0,0 +1,104 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the navigation control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlNavigation + { + /// + /// Tests the id property of the navigation control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                        ")] + [InlineData("id", @"
                                                                                                                                                          ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigation(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the navigation control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                            ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                              ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                    ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                          ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigation() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the layout property of the navigation control. + /// + [Theory] + [InlineData(TypeLayoutTab.Default, @"
                                                                                                                                                                            ")] + [InlineData(TypeLayoutTab.Menu, @"
                                                                                                                                                                              ")] + [InlineData(TypeLayoutTab.Tab, @"
                                                                                                                                                                                ")] + [InlineData(TypeLayoutTab.Pill, @"
                                                                                                                                                                                  ")] + public void Layout(TypeLayoutTab layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigation() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the navigation control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigation(); + + // test execution + control.Add(new ControlNavigationItemLink() { Text = "abc" }); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs new file mode 100644 index 00000000..d92d1545 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs @@ -0,0 +1,306 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the navigation item dropdown control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlNavigationItemDropdown + { + /// + /// Tests the id property of the navigation item dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                    ")] + [InlineData("id", @"
                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"
                                                                                                                                                                                        ")] + [InlineData(TypeColorButton.Primary, @"
                                                                                                                                                                                          ")] + [InlineData(TypeColorButton.Secondary, @"
                                                                                                                                                                                            ")] + [InlineData(TypeColorButton.Info, @"
                                                                                                                                                                                              ")] + [InlineData(TypeColorButton.Warning, @"
                                                                                                                                                                                                ")] + [InlineData(TypeColorButton.Danger, @"
                                                                                                                                                                                                  ")] + [InlineData(TypeColorButton.Light, @"
                                                                                                                                                                                                    ")] + [InlineData(TypeColorButton.Dark, @"
                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorButton backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + BackgroundColor = new PropertyColorButton(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"
                                                                                                                                                                                                        ")] + [InlineData(TypeSizeButton.Small, @"
                                                                                                                                                                                                          ")] + [InlineData(TypeSizeButton.Large, @"
                                                                                                                                                                                                            ")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the navigation item dropdown control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                                                                                              ")] + [InlineData(true, @"
                                                                                                                                                                                                                ")] + public void Outline(bool outline, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Outline = outline, + BackgroundColor = new PropertyColorButton(TypeColorButton.Primary) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the block property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"
                                                                                                                                                                                                                  ")] + [InlineData(TypeBlockButton.Block, @"
                                                                                                                                                                                                                    ")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the toogle property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeToggleDropdown.None, @"
                                                                                                                                                                                                                      ")] + [InlineData(TypeToggleDropdown.Toggle, @"
                                                                                                                                                                                                                        ")] + public void Toogle(TypeToggleDropdown toogle, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Toogle = toogle + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the navigation item dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                          ")] + [InlineData("abc", @"
                                                                                                                                                                                                                            ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                                                                                                                                                              ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tooltip property of the navigation item dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                  ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                                                                                                                                                                    ")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Tooltip = tooltip, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the navigation item dropdown control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                        ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                                                                                                                                                                          ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Value = value, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the icon property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                                                                                                                            ")] + [InlineData(TypeIcon.Star, @"
                                                                                                                                                                                                                                              ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the active property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeActive.None, @"
                                                                                                                                                                                                                                                ")] + [InlineData(TypeActive.Active, @"
                                                                                                                                                                                                                                                  ")] + [InlineData(TypeActive.Disabled, @"
                                                                                                                                                                                                                                                    ")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + Active = active + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the alignment menu property of the navigation item dropdown control. + /// + [Theory] + [InlineData(TypeAlignmentDropdownMenu.Default, @"
                                                                                                                                                                                                                                                      ")] + [InlineData(TypeAlignmentDropdownMenu.Right, @"
                                                                                                                                                                                                                                                        ")] + public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown() + { + AlignmentMenu = alignmentMenu + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the navigation item dropdown control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemDropdown(); + + // test execution + control.Add(new ControlDropdownItemLink() { Text = "abc" }); + + var html = control.Render(context); + + Assert.Equal(@"", html.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs new file mode 100644 index 00000000..00dcd674 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs @@ -0,0 +1,56 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the navigation item header control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlNavigationItemHeader + { + /// + /// Tests the id property of the navigation item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                      • ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                      • ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemHeader(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the navigation item header control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                      • ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                                      • abc
                                                                                                                                                                                                                                                      • ")] + [InlineData("webexpress.WebUI:plugin.name", @"
                                                                                                                                                                                                                                                      • WebExpress.WebUI
                                                                                                                                                                                                                                                      • ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlNavigationItemHeader() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs new file mode 100644 index 00000000..34a0a88d --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs @@ -0,0 +1,104 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel footer control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelFooter + { + /// + /// Tests the id property of the panel footer control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                        ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                        ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFooter(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the panel footer control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                        ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFooter() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the panel footer control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                        ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelFooter() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the panel footer control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                        ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelFooter(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs new file mode 100644 index 00000000..42467274 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs @@ -0,0 +1,104 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel main control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelMain + { + /// + /// Tests the id property of the panel main control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                        ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                        ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMain(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the panel main control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                        ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMain() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the panel main control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                        ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMain() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the panel main control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                        ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelMain(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs new file mode 100644 index 00000000..68825c9f --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs @@ -0,0 +1,109 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel split control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelSplit + { + /// + /// Tests the id property of the panel split control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                        ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                        ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelSplit(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the orientation property of the panel split control. + /// + [Theory] + [InlineData(TypeOrientationSplit.Horizontal, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeOrientationSplit.Vertical, @"
                                                                                                                                                                                                                                                        ")] + public void Orientation(TypeOrientationSplit orientation, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelSplit() + { + Orientation = orientation, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the splitter color property of the panel split control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                        ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                        ")] + + public void SplitterColor(TypeColorBackground splitterColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelSplit() + { + SplitterColor = new PropertyColorBackground(splitterColor), + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the panel split control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                        ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                        ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance1 = Activator.CreateInstance(child, [null]) as IControl; + var childInstance2 = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelSplit(); + + // test execution + control.AddPanel1(childInstance1); + control.AddPanel2(childInstance2); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs b/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs deleted file mode 100644 index 4f52b51b..00000000 --- a/src/WebExpress.WebUI/WebAttribute/OptionAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -ο»Ώusing System; -using WebExpress.WebCore.WebAttribute; - -namespace WebExpress.WebUI.WebAttribute -{ - /// - /// Activation of options (e.g. WebEx.WebApp.Setting.SystemInformation for the display of system information). - /// - [AttributeUsage(AttributeTargets.Class)] - public class OptionAttribute : System.Attribute, IEndpointAttribute - { - /// - /// Initializes a new instance of the class. - /// - /// The option to activate. - public OptionAttribute(string option) - { - - } - } -} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs index 89c173c2..75551080 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroup.cs @@ -9,6 +9,7 @@ namespace WebExpress.WebUI.WebControl public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation { private readonly List _items = []; + private readonly List _validationResults = []; /// /// Returns the form items. @@ -18,7 +19,7 @@ public abstract class ControlFormItemGroup : ControlFormItem, IFormValidation /// /// Determines whether the inputs are valid. /// - public ICollection ValidationResults { get; } = new List(); + public IEnumerable ValidationResults => _validationResults; /// /// Returns or sets whether the form element has been validated. @@ -87,7 +88,7 @@ public void Add(params ControlFormItem[] items) /// maintaining the order of addition. /// This method accepts any item that derives from . /// - public void Add(IEnumerable items) + public virtual void Add(IEnumerable items) { _items.AddRange(items); } @@ -101,11 +102,41 @@ public void Add(IEnumerable items) /// current form of items. If the item does not exist in the list, the method does nothing. /// This method accepts any item that derives from . /// - public void Remove(ControlFormItem item) + public virtual void Remove(ControlFormItem item) { _items.Remove(item); } + /// + /// Adds a collection of validation results to the existing validation results. + /// + /// The validation results to add. + /// + /// This method appends the specified collection of instances to the + /// current list of validation results. It ensures that the new validation results are concatenated + /// with the existing ones, maintaining the order of addition. + /// This method accepts any item that derives from . + /// + public virtual void AddValidationResult(params ValidationResult[] validationResults) + { + _validationResults.AddRange(validationResults); + } + + /// + /// Removes a specified validation result from the existing validation results. + /// + /// The validation result to remove. + /// + /// This method removes the specified instance from the + /// current list of validation results. If the validation result does not exist in the list, + /// the method does nothing. + /// This method accepts any item that derives from . + /// + public void RemoveValidationResult(ValidationResult validationResult) + { + _validationResults.Remove(validationResult); + } + /// /// Initializes the form element. /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs index 041f0b14..31047896 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInput.cs @@ -12,6 +12,7 @@ namespace WebExpress.WebUI.WebControl /// public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, IFormValidation { + private readonly List _validationResults = []; private readonly List _prepend = []; private readonly List _append = []; @@ -20,6 +21,11 @@ public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, /// public event EventHandler Validation; + /// + /// Determines whether the inputs are valid. + /// + public virtual IEnumerable ValidationResults => _validationResults; + /// /// Returns or sets the icon. /// @@ -60,11 +66,6 @@ public abstract class ControlFormItemInput : ControlFormItem, IControlFormLabel, /// public object Tag { get; set; } - /// - /// Determines whether the inputs are valid. - /// - public virtual ICollection ValidationResults { get; } = new List(); - /// /// Returns the most serious validation result. /// @@ -106,10 +107,10 @@ public ControlFormItemInput(string id) IsValidated = false; } - // - // Adds one or more controls to the prepend list. - // - // The controls to add. + /// + /// Adds one or more controls to the prepend list. + /// + /// The controls to add. public void AddPrepend(params IControl[] controls) { _prepend.AddRange(controls); @@ -141,6 +142,30 @@ public void RemoveAppend(IControl control) _append.Remove(control); } + /// + /// Adds a collection of validation results to the existing validation results. + /// + /// The validation results to add. + /// + /// This method appends the specified collection of instances to the + /// current list of validation results. It ensures that the new validation results are concatenated + /// with the existing ones, maintaining the order of addition. + /// This method accepts any item that derives from . + /// + public virtual void AddValidationResult(params ValidationResult[] validationResults) + { + _validationResults.AddRange(validationResults); + } + + /// + /// Removes a validation result from the validation results collection. + /// + /// The control to remove. + public virtual void RemoveValidationResult(ValidationResult validationResult) + { + _validationResults.Remove(validationResult); + } + /// /// Initializes the form emement. /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs index 69f34d36..7f7defca 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs @@ -75,7 +75,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) foreach (var v in Items) { - if (v.SubItems.Count() > 0) + if (v.SubItems.Any()) { html.Add(new HtmlElementFormOptgroup() { Label = v.Text }); foreach (var s in v.SubItems) diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs index 25fd19c1..3d5ab3a7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs @@ -1,129 +1,129 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebUri; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputDatepicker : ControlFormItemInput -// { -// /// -// /// Determines whether the control is automatically initialized. -// /// -// public bool AutoInitialize { get; set; } - -// /// -// /// Returns or sets the description. -// /// -// public string Description { get; set; } - -// /// -// /// Returns or sets the minimum length. -// /// -// public string MinLength { get; set; } - -// /// -// /// Returns or sets the maximum length. -// /// -// public string MaxLength { get; set; } - -// /// -// /// Returns or sets whether inputs are enforced. -// /// -// public bool Required { get; set; } - -// /// -// /// Returns or sets a search pattern that checks the content. -// /// -// public string Pattern { get; set; } - -// ///// -// ///// Returns the initialization code (JQuerry). -// ///// -// //public string InitializeCode => "$('#" + Id + " input').datepicker({ startDate: -3 });"; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputDatepicker(string id = null) -// : base(!string.IsNullOrWhiteSpace(id) ? id : "datepicker") -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// AutoInitialize = true; - -// var contextPath = context.PageContext?.ApplicationContext?.ContextPath; - -// Value = context?.Request.GetParameter(Name)?.Value; - -// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap-datepicker.min.js")); -// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/locales_datepicker/bootstrap-datepicker." + context.Culture.TwoLetterISOLanguageName.ToLower() + ".min.js")); -// context.VisualTree.CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap-datepicker3.min.css")); - -// context.AddScript(Id, @"$('#" + Id + @"').datepicker({format: ""dd.mm.yyyy"", todayBtn: true, language: ""de"", zIndexOffset: 999});"); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { - - -// //if (Disabled) -// //{ -// // Classes.Add("disabled"); -// //} - -// //if (AutoInitialize) -// //{ -// // context.Page.AddScript(Id, InitializeCode); -// // AutoInitialize = false; -// //} - -// var input = new HtmlElementFieldInput() -// { -// Id = Id, -// Name = Name, -// Type = "text", -// Class = "form-control", -// Value = Value -// }; - -// //var span = new HtmlElementTextSemanticsSpan() -// //{ -// // Class = TypeIcon.Calendar.ToClass() -// //}; - -// //var div = new HtmlElementTextContentDiv(span) -// //{ -// // Class = "input-group-text" -// //}; - -// //var html = new HtmlElementTextContentDiv(input, div) -// //{ -// // Id = Id, -// // Class = "input-group", -// // //DataProvide = "datepicker" -// //}; - -// return input; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } -// } -//} +ο»Ώusing WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a date picker input form item control. + /// + public class ControlFormItemInputDatepicker : ControlFormItemInput + { + /// + /// Determines whether the control is automatically initialized. + /// + public bool AutoInitialize { get; set; } + + /// + /// Returns or sets the description. + /// + public string Description { get; set; } + + /// + /// Returns or sets the minimum length. + /// + public string MinLength { get; set; } + + /// + /// Returns or sets the maximum length. + /// + public string MaxLength { get; set; } + + /// + /// Returns or sets whether inputs are enforced. + /// + public bool Required { get; set; } + + /// + /// Returns or sets a search pattern that checks the content. + /// + public string Pattern { get; set; } + + ///// + ///// Returns the initialization code (JQuerry). + ///// + //public string InitializeCode => "$('#" + Id + " input').datepicker({ startDate: -3 });"; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInputDatepicker(string id = null) + : base(!string.IsNullOrWhiteSpace(id) ? id : "datepicker") + { + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + AutoInitialize = true; + + var contextPath = renderContext.PageContext?.ApplicationContext?.ContextPath; + + Value = renderContext?.Request.GetParameter(Name)?.Value; + + //renderContext.AddHeaderScriptLinks(UriResource.Combine(contextPath, "/assets/js/bootstrap-datepicker.min.js")); + //renderContext.AddHeaderScriptLinks(UriResource.Combine(contextPath, "/assets/js/locales_datepicker/bootstrap-datepicker." + context.Culture.TwoLetterISOLanguageName.ToLower() + ".min.js")); + //renderContext.AddCssLinks(UriResource.Combine(contextPath, "/assets/css/bootstrap-datepicker3.min.css")); + + //renderContext.AddScript(Id, @"$('#" + Id + @"').datepicker({format: ""dd.mm.yyyy"", todayBtn: true, language: ""de"", zIndexOffset: 999});"); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + //if (Disabled) + //{ + // Classes.Add("disabled"); + //} + + //if (AutoInitialize) + //{ + // context.Page.AddScript(Id, InitializeCode); + // AutoInitialize = false; + //} + + var input = new HtmlElementFieldInput() + { + Id = Id, + Name = Name, + Type = "text", + Class = "form-control", + Value = Value + }; + + //var span = new HtmlElementTextSemanticsSpan() + //{ + // Class = TypeIcon.Calendar.ToClass() + //}; + + //var div = new HtmlElementTextContentDiv(span) + //{ + // Class = "input-group-text" + //}; + + //var html = new HtmlElementTextContentDiv(input, div) + //{ + // Id = Id, + // Class = "input-group", + // //DataProvide = "datepicker" + //}; + + return input; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs index 3bfd7f26..5106cf19 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs @@ -1,114 +1,130 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputFile : ControlFormItemInput -// { -// /// -// /// Returns or sets the description. -// /// -// public string Description { get; set; } - -// /// -// /// Returns or sets a placeholder text. -// /// -// public string Placeholder { get; set; } - -// /// -// /// Returns or sets whether inputs are enforced. -// /// -// public bool Required { get; set; } - -// /// -// /// Returns or sets the accepted files. -// /// -// public ICollection AcceptFile { get; set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputFile(string id = null) -// : base(!string.IsNullOrWhiteSpace(id) ? id : "file") -// { -// Name = Id; -// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The name. -// public ControlFormItemInputFile(string id, string name) -// : base(!string.IsNullOrWhiteSpace(id) ? id : "file") -// { -// Name = name; -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// Value = context?.Request.GetParameter(Name)?.Value; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// switch (ValidationResult) -// { -// case TypesInputValidity.Warning: -// Classes.Add("input-warning"); -// break; -// case TypesInputValidity.Error: -// Classes.Add("input-error"); -// break; -// } - -// var html = new HtmlElementFieldInput() -// { -// Id = Id, -// Value = Value, -// Name = Name, -// Type = "file", -// Class = Css.Concatenate("form-control-file", GetClasses()), -// Style = GetStyles(), -// Role = Role, -// Placeholder = Placeholder -// }; - -// html.AddUserAttribute("accept", string.Join(",", AcceptFile)); - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// if (Disabled) -// { -// return; -// } - -// if (Required && string.IsNullOrWhiteSpace(base.Value)) -// { -// ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputfile.validation.required")); - -// return; -// } - -// base.Validate(context); -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item input control for file uploads. + /// + /// + /// This control allows users to select files to upload. It supports setting descriptions, placeholders, + /// required fields, and accepted file types. It also provides validation and rendering functionalities. + /// + public class ControlFormItemInputFile : ControlFormItemInput + { + private readonly List _acceptFile = []; + + /// + /// Returns or sets the description. + /// + public string Description { get; set; } + + /// + /// Returns or sets a placeholder text. + /// + public string Placeholder { get; set; } + + /// + /// Returns or sets whether inputs are enforced. + /// + public bool Required { get; set; } + + /// + /// Returns or sets the accepted files. + /// + public IEnumerable AcceptFile => _acceptFile; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInputFile(string id = null) + : base(!string.IsNullOrWhiteSpace(id) ? id : "file") + { + Name = Id; + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); + } + + /// + /// Adds one or more accepted file types to the control. + /// + /// The file types to add. + public void AddAcceptFile(params string[] controls) + { + _acceptFile.AddRange(controls); + } + + /// + /// Removes an accepted file type from the control. + /// + /// The file type to remove. + public void RemoveAcceptFile(string control) + { + _acceptFile.Remove(control); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + Value = renderContext?.Request.GetParameter(Name)?.Value; + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + switch (ValidationResult) + { + case TypesInputValidity.Warning: + Classes.Add("input-warning"); + break; + case TypesInputValidity.Error: + Classes.Add("input-error"); + break; + } + + var html = new HtmlElementFieldInput() + { + Id = Id, + Value = Value, + Name = Name, + Type = "file", + Class = Css.Concatenate("form-control-file", GetClasses()), + Style = GetStyles(), + Role = Role, + Placeholder = Placeholder + }; + + html.AddUserAttribute("accept", string.Join(",", AcceptFile)); + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + if (Disabled) + { + return; + } + + if (Required && string.IsNullOrWhiteSpace(base.Value)) + { + AddValidationResult(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputfile.validation.required")); + + return; + } + + base.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs index 3e4e8e8d..40499275 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs @@ -1,82 +1,75 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputGroup : ControlFormItemInput -// { -// /// -// /// Returns or sets the group. -// /// -// public ControlFormItemGroup Group { get; private set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item input group control. + /// + public class ControlFormItemInputGroup : ControlFormItemInput + { + /// + /// Returns the group. + /// + public ControlFormItemGroup Group { get; private set; } -// /// -// /// Determines whether the inputs are valid. -// /// -// public override ICollection ValidationResults => Group != null ? Group.ValidationResults : new List(); + /// + /// Determines whether the inputs are valid. + /// + public override IEnumerable ValidationResults => Group != null ? Group.ValidationResults : []; -// /// -// /// Returns the most serious validation result. -// /// -// public override TypesInputValidity ValidationResult => Group != null ? Group.ValidationResult : TypesInputValidity.Default; + /// + /// Returns the most serious validation result. + /// + public override TypesInputValidity ValidationResult => Group != null ? Group.ValidationResult : TypesInputValidity.Default; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputGroup(string id = null) -// : base(id) -// { -// Name = Id; -// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The group of form items. + public ControlFormItemInputGroup(string id = null, ControlFormItemGroup group = null) + : base(id) + { + Name = id; + Group = group; + Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The name. -// public ControlFormItemInputGroup(string id, ControlFormItemGroup group) -// : base(id) -// { -// Name = id; -// Group = group; -// } + /// + /// Initializes the form emement. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + if (Group != null) + { + Group.Initialize(renderContext); + } + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// if (Group != null) -// { -// Group.Initialize(context); -// } -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + return Group?.Render(renderContext); + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// return Group?.Render(context); -// } + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public virtual void Validate(IRenderControlFormContext renderContext) + { + if (Disabled) + { + return; + } -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// if (Disabled) -// { -// return; -// } - -// Group.Validate(context); -// } -// } -//} + Group.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs index 6b918591..1c31755b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs @@ -1,150 +1,162 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Text.Json; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputMove : ControlFormItemInput -// { -// /// -// /// Returns the entries. -// /// -// public ICollection Options { get; } = new List(); - -// /// -// /// Returns or sets the label of the selected options. -// /// -// public string SelectedHeader { get; set; } = "webexpress.webui:form.selectionmove.selected"; - -// /// -// /// Returns or sets the label. -// /// -// public string AvailableHeader { get; set; } = "webexpress.webui:form.selectionmove.available"; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputMove(string id = null) -// : base(string.IsNullOrEmpty(id) ? typeof(ControlFormItemInputSelection).GUID.ToString() : id) -// { -// Name = Id; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The entries. -// public ControlFormItemInputMove(string id, params ControlFormItemInputSelectionItem[] items) -// : this(id) -// { -// (Options as List).AddRange(items); -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// if (context.Request.HasParameter(Name)) -// { -// Value = context?.Request.GetParameter(Name)?.Value; -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var classes = Classes.ToList(); - -// if (Disabled) -// { -// classes.Add("disabled"); -// } - -// switch (ValidationResult) -// { -// case TypesInputValidity.Warning: -// classes.Add("input-warning"); -// break; -// case TypesInputValidity.Error: -// classes.Add("input-error"); -// break; -// } - -// var html = new HtmlElementTextContentDiv() -// { -// Id = $"selection-move-{Id}", -// Style = GetStyles() -// }; - -// context.AddScript(Id, GetScript(context, $"selection-move-{Id}", string.Join(" ", classes))); - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } - -// /// -// /// Generates the javascript to control the control. -// /// -// /// The context in which the control is rendered. -// /// The id of the control. -// /// The css classes that are assigned to the control. -// /// The javascript code. -// protected virtual string GetScript(RenderContextForm context, string id, string css) -// { -// var settings = new -// { -// Id = id, -// Name = Id, -// CSS = css, -// Header = new -// { -// Selected = I18N.Translate(SelectedHeader), -// Available = I18N.Translate(AvailableHeader) -// }, -// Buttons = new -// { -// ToSelectedAll = I18N.Translate("Λ‚Λ‚"), -// ToSelected = I18N.Translate("Λ‚"), -// ToAvailableAll = I18N.Translate("ΛƒΛƒ"), -// ToAvailable = I18N.Translate("Λƒ") -// } -// }; - -// var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; -// var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); -// var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); -// var valuesJson = JsonSerializer.Serialize(Value?.Split(";", System.StringSplitOptions.RemoveEmptyEntries), jsonOptions); -// var builder = new StringBuilder(); - -// builder.Append($"var options = {optionsJson};"); -// builder.Append($"var settings = {settingsJson};"); -// builder.Append($"var container = $('#{id}');"); -// builder.Append($"var obj = new webexpress.webui.moveCtrl(settings);"); -// builder.Append($"obj.options = options;"); -// builder.Append($"obj.value = {(!string.IsNullOrWhiteSpace(valuesJson) ? valuesJson : "[]")};"); -// builder.Append($"container.replaceWith(obj.getCtrl);"); - -// return builder.ToString(); -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item input control that allows moving items between available and selected lists. + /// + public class ControlFormItemInputMove : ControlFormItemInput + { + private readonly List _options = []; + + /// + /// Returns the entries. + /// + public IEnumerable Options => _options; + + /// + /// Returns or sets the label of the selected options. + /// + public string SelectedHeader { get; set; } = "webexpress.webui:form.selectionmove.selected"; + + /// + /// Returns or sets the label. + /// + public string AvailableHeader { get; set; } = "webexpress.webui:form.selectionmove.available"; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The entries. + public ControlFormItemInputMove(string id = null, params ControlFormItemInputSelectionItem[] items) + : base(string.IsNullOrEmpty(id) ? typeof(ControlFormItemInputSelection).GUID.ToString() : id) + { + _options.AddRange(items); + } + + /// + /// Adds one or more items to the selection options. + /// + /// The items to add to the selection options. + public void Add(params ControlFormItemInputSelectionItem[] items) + { + _options.AddRange(items); + } + + /// + /// Removes an item from the selection options. + /// + /// The item to remove from the selection options. + public void Remove(ControlFormItemInputSelectionItem item) + { + _options.Remove(item); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + if (renderContext.Request.HasParameter(Name)) + { + Value = renderContext?.Request.GetParameter(Name)?.Value; + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var classes = Classes.ToList(); + + if (Disabled) + { + classes.Add("disabled"); + } + + switch (ValidationResult) + { + case TypesInputValidity.Warning: + classes.Add("input-warning"); + break; + case TypesInputValidity.Error: + classes.Add("input-error"); + break; + } + + var html = new HtmlElementTextContentDiv() + { + Id = $"selection-move-{Id}", + Style = GetStyles() + }; + + renderContext.AddScript(Id, GetScript($"selection-move-{Id}", string.Join(" ", classes))); + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + + /// + /// Generates the javascript to control the control. + /// + /// The id of the control. + /// The css classes that are assigned to the control. + /// The javascript code. + protected virtual string GetScript(string id, string css) + { + var settings = new + { + Id = id, + Name = Id, + CSS = css, + Header = new + { + Selected = I18N.Translate(SelectedHeader), + Available = I18N.Translate(AvailableHeader) + }, + Buttons = new + { + ToSelectedAll = I18N.Translate("Λ‚Λ‚"), + ToSelected = I18N.Translate("Λ‚"), + ToAvailableAll = I18N.Translate("ΛƒΛƒ"), + ToAvailable = I18N.Translate("Λƒ") + } + }; + + var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; + var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); + var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); + var valuesJson = JsonSerializer.Serialize(Value?.Split(";", System.StringSplitOptions.RemoveEmptyEntries), jsonOptions); + var builder = new StringBuilder(); + + builder.Append($"var options = {optionsJson};"); + builder.Append($"var settings = {settingsJson};"); + builder.Append($"var container = $('#{id}');"); + builder.Append($"var obj = new webexpress.webui.moveCtrl(settings);"); + builder.Append($"obj.options = options;"); + builder.Append($"obj.value = {(!string.IsNullOrWhiteSpace(valuesJson) ? valuesJson : "[]")};"); + builder.Append($"container.replaceWith(obj.getCtrl);"); + + return builder.ToString(); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs index 63b04985..49ff3120 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs @@ -1,128 +1,123 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputRadio : ControlFormItemInput -// { -// /// -// /// Returns or sets the value of the optiopn. -// /// -// public string Option { get; set; } - -// /// -// /// Liefert oder setzt ob die Checkbox in einer neuen Zeile angezeigt werden soll -// /// -// public bool Inline { get; set; } - -// /// -// /// Returns or sets the description. -// /// -// public string Description { get; set; } - -// /// -// /// Returns or sets a search pattern that checks the content. -// /// -// public string Pattern { get; set; } - -// /// -// /// Returns or sets whether the radio button is selected -// /// -// public bool Checked { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputRadio(string id = null) -// : base(id) -// { - -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The name. -// public ControlFormItemInputRadio(string id, string name) -// : this(id) -// { -// Name = name; -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// if (!string.IsNullOrWhiteSpace(Value)) -// { -// Checked = Value == Option; -// } - -// var c = new List -// { -// "radio" -// }; - -// if (Inline) -// { -// c.Add("form-check-inline"); -// } - -// if (Disabled) -// { -// c.Add("disabled"); -// } - -// var html = new HtmlElementTextContentDiv -// ( -// new HtmlElementFieldLabel -// ( -// new HtmlElementFieldInput() -// { -// Id = Id, -// Name = Name, -// Pattern = Pattern, -// Type = "radio", -// Disabled = Disabled, -// Checked = Checked, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// Value = Option -// }, -// new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + Description) -// ) -// { -// } -// ) -// { -// Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))) -// }; - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a radio button input form item control. + /// + /// + /// This class provides the functionality for a radio button input within a form. + /// + public class ControlFormItemInputRadio : ControlFormItemInput + { + /// + /// Returns or sets the value of the optiopn. + /// + public string Option { get; set; } + + /// + /// Liefert oder setzt ob die Checkbox in einer neuen Zeile angezeigt werden soll + /// + public bool Inline { get; set; } + + /// + /// Returns or sets the description. + /// + public string Description { get; set; } + + /// + /// Returns or sets a search pattern that checks the content. + /// + public string Pattern { get; set; } + + /// + /// Returns or sets whether the radio button is selected + /// + public bool Checked { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemInputRadio(string id = null) + : base(id) + { + + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + if (!string.IsNullOrWhiteSpace(Value)) + { + Checked = Value == Option; + } + + var c = new List + { + "radio" + }; + + if (Inline) + { + c.Add("form-check-inline"); + } + + if (Disabled) + { + c.Add("disabled"); + } + + var html = new HtmlElementTextContentDiv + ( + new HtmlElementFieldLabel + ( + new HtmlElementFieldInput() + { + Id = Id, + Name = Name, + Pattern = Pattern, + Type = "radio", + Disabled = Disabled, + Checked = Checked, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + Value = Option + }, + new HtmlText(string.IsNullOrWhiteSpace(Description) ? string.Empty : " " + Description) + ) + { + } + ) + { + Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))) + }; + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs index 737314a3..afa89344 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs @@ -1,161 +1,175 @@ -ο»Ώ//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Text.Json; -//using WebExpress.WebCore.WebHtml; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputSelection : ControlFormItemInput -// { -// /// -// /// Returns the entries. -// /// -// public ICollection Options { get; } = []; - -// /// -// /// Returns or sets the label of the selected options. -// /// -// public string Placeholder { get; set; } - -// /// -// /// Returns or sets whether to display the description of the option or hide it. -// /// -// public bool HideDescription { get; set; } - -// /// -// /// Allows you to select multiple items. -// /// -// public bool MultiSelect { get; set; } - -// /// -// /// Returns or sets the OnChange attribute. -// /// -// public PropertyOnChange OnChange { get; set; } - -// /// -// /// Returns or sets the value. -// /// -// public virtual ICollection Values => base.Value != null ? base.Value.Split(';', System.StringSplitOptions.RemoveEmptyEntries) : []; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemInputSelection(string id = null) -// : base(id ?? Guid.NewGuid().ToString()) -// { -// Name = Id; -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The entries. -// public ControlFormItemInputSelection(string id, params ControlFormItemInputSelectionItem[] items) -// : this(id) -// { -// (Options as List).AddRange(items); -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// if (context.Request.HasParameter(Name)) -// { -// Value = context?.Request.GetParameter(Name)?.Value; -// } -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var classes = Classes.ToList(); - -// if (Disabled) -// { -// classes.Add("disabled"); -// } - -// switch (ValidationResult) -// { -// case TypesInputValidity.Warning: -// classes.Add("input-warning"); -// break; -// case TypesInputValidity.Error: -// classes.Add("input-error"); -// break; -// } - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Style = GetStyles() -// }; - -// context.AddScript(Id, GetScript(context, Id, string.Join(" ", classes))); - -// return html; -// } - -// /// -// /// Checks the input element for correctness of the data. -// /// -// /// The context in which the inputs are validated. -// public override void Validate(RenderContextForm context) -// { -// base.Validate(context); -// } - -// /// -// /// Generates the javascript to control the control. -// /// -// /// The context in which the control is rendered. -// /// The ID of the control. -// /// The CSS classes that are assigned to the control. -// /// The javascript code. -// protected virtual string GetScript(RenderContextForm context, string id, string css) -// { -// var settings = new -// { -// id = id, -// name = Id, -// css = css, -// placeholder = Placeholder, -// hidedescription = HideDescription, -// multiselect = MultiSelect -// }; - -// var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; -// var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); -// var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); -// var builder = new StringBuilder(); - -// builder.AppendLine($"let options = {optionsJson};"); -// builder.AppendLine($"let settings = {settingsJson};"); -// builder.AppendLine($"let container = $('#{id}');"); -// builder.AppendLine($"let obj = new webexpress.webui.selectionCtrl(settings);"); -// builder.AppendLine($"obj.options = options;"); -// builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];"); - -// if (OnChange != null) -// { -// builder.AppendLine($"obj.on('webexpress.webui.change.value', {OnChange});"); -// } - -// builder.AppendLine($"container.replaceWith(obj.getCtrl);"); - -// return builder.ToString(); -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using WebExpress.WebCore.WebHtml; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item input control for selection. + /// + /// + /// This control allows users to select one or more options from a predefined list. + /// + public class ControlFormItemInputSelection : ControlFormItemInput + { + private readonly List _options = []; + + /// + /// Returns the entries. + /// + public IEnumerable Options => _options; + + /// + /// Returns or sets the label of the selected options. + /// + public string Placeholder { get; set; } + + /// + /// Returns or sets whether to display the description of the option or hide it. + /// + public bool HideDescription { get; set; } + + /// + /// Allows you to select multiple items. + /// + public bool MultiSelect { get; set; } + + /// + /// Returns or sets the OnChange attribute. + /// + public PropertyOnChange OnChange { get; set; } + + /// + /// Returns or sets the value. + /// + public virtual IEnumerable Values => base.Value != null ? base.Value.Split(';', System.StringSplitOptions.RemoveEmptyEntries) : []; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The entries. + public ControlFormItemInputSelection(string id = null, params ControlFormItemInputSelectionItem[] items) + : base(id) + { + _options.AddRange(items); + } + + /// + /// Adds one or more items to the selection options. + /// + /// The items to add to the selection options. + public void Add(params ControlFormItemInputSelectionItem[] items) + { + _options.AddRange(items); + } + + /// + /// Removes an item from the selection options. + /// + /// The item to remove from the selection options. + public void Remove(ControlFormItemInputSelectionItem item) + { + _options.Remove(item); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + if (renderContext.Request.HasParameter(Name)) + { + Value = renderContext?.Request.GetParameter(Name)?.Value; + } + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var classes = Classes.ToList(); + + if (Disabled) + { + classes.Add("disabled"); + } + + switch (ValidationResult) + { + case TypesInputValidity.Warning: + classes.Add("input-warning"); + break; + case TypesInputValidity.Error: + classes.Add("input-error"); + break; + } + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Style = GetStyles() + }; + + renderContext.AddScript(Id, GetScript(Id, string.Join(" ", classes))); + + return html; + } + + /// + /// Checks the input element for correctness of the data. + /// + /// The context in which the inputs are validated. + public override void Validate(IRenderControlFormContext renderContext) + { + base.Validate(renderContext); + } + + /// + /// Generates the javascript to control the control. + /// + /// The ID of the control. + /// The CSS classes that are assigned to the control. + /// The javascript code. + protected virtual string GetScript(string id, string css) + { + var settings = new + { + id = id, + name = Id, + css = css, + placeholder = Placeholder, + hidedescription = HideDescription, + multiselect = MultiSelect + }; + + var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; + var settingsJson = JsonSerializer.Serialize(settings, jsonOptions); + var optionsJson = JsonSerializer.Serialize(Options, jsonOptions); + var builder = new StringBuilder(); + + builder.AppendLine($"let options = {optionsJson};"); + builder.AppendLine($"let settings = {settingsJson};"); + builder.AppendLine($"let container = $('#{id}');"); + builder.AppendLine($"let obj = new webexpress.webui.selectionCtrl(settings);"); + builder.AppendLine($"obj.options = options;"); + builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];"); + + if (OnChange != null) + { + builder.AppendLine($"obj.on('webexpress.webui.change.value', {OnChange});"); + } + + builder.AppendLine($"container.replaceWith(obj.getCtrl);"); + + return builder.ToString(); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs index 3dd869eb..3986cb53 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelectionItem.cs @@ -1,49 +1,52 @@ -ο»Ώ//using System.Text.Json.Serialization; +ο»Ώusing System.Text.Json.Serialization; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemInputSelectionItem -// { -// /// -// /// Returns or sets Returns or sets the id. -// /// -// [JsonPropertyName("id")] -// public string Id { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents an item in a selection input form. + /// + public class ControlFormItemInputSelectionItem + { + /// + /// Returns or sets Returns or sets the id. + /// + [JsonPropertyName("id")] + public string Id { get; set; } -// /// -// /// Returns or sets the label. -// /// -// [JsonPropertyName("label")] -// public string Label { get; set; } + /// + /// Returns or sets the label. + /// + [JsonPropertyName("label")] + public string Label { get; set; } -// /// -// /// Returns or sets the css class of the icon. -// /// -// [JsonPropertyName("icon")] -// public string Icon { get; set; } + /// + /// Returns or sets the css class of the icon. + /// + [JsonPropertyName("icon")] + public string Icon { get; set; } -// /// -// /// Returns or sets the uri of the image. -// /// -// [JsonPropertyName("image")] -// public string Image { get; set; } + /// + /// Returns or sets the uri of the image. + /// + [JsonPropertyName("image")] + public string Image { get; set; } -// /// -// /// Returns or sets the description. -// /// -// [JsonPropertyName("description")] -// public string Description { get; set; } + /// + /// Returns or sets the description. + /// + [JsonPropertyName("description")] + public string Description { get; set; } -// /// -// /// Returns or sets the color. -// /// -// [JsonPropertyName("color")] -// public string Color { get; set; } + /// + /// Returns or sets the color. + /// + [JsonPropertyName("color")] + public string Color { get; set; } -// /// -// /// Returns or sets the command (e.g. Add). -// /// -// [JsonPropertyName("instruction")] -// public string Instruction { get; set; } -// } -//} + /// + /// Returns or sets the command (e.g. Add). + /// + [JsonPropertyName("instruction")] + public string Instruction { get; set; } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs index 68881609..e7d055d2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs @@ -180,19 +180,19 @@ public override void Validate(IRenderControlFormContext renderContext) if (Required && string.IsNullOrWhiteSpace(base.Value)) { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); + AddValidationResult(new ValidationResult(TypesInputValidity.Error, "webexpress.webui:form.inputtextbox.validation.required")); return; } if (!string.IsNullOrWhiteSpace(MinLength?.ToString()) && Convert.ToInt32(MinLength) > base.Value.Length) { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); + AddValidationResult(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.min"), MinLength))); } if (!string.IsNullOrWhiteSpace(MaxLength?.ToString()) && Convert.ToInt32(MaxLength) < base.Value.Length) { - ValidationResults.Add(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); + AddValidationResult(new ValidationResult(TypesInputValidity.Error, string.Format(I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.inputtextbox.validation.max"), MaxLength))); } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs index a101066e..fd53256a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs @@ -1,71 +1,33 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemPrepend : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemPrepend(string id) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a form item that is prepended to an input group. + /// + public class ControlFormItemPrepend : ControlFormItemPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlFormItemPrepend(string id = null, params Control[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlFormItemPrepend(string id, params Control[] content) -// : base(id, content) -// { -// Init(); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + Classes.Add("input-group-prepend"); + var html = base.Render(renderContext); -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlFormItemPrepend(string id, IEnumerable content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlFormItemPrepend(string id, List content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// Classes.Add("input-group-prepend"); -// var html = base.Render(context); -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs index 7b1c49f8..61fe3847 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs @@ -1,59 +1,63 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlFormItemStaticText : ControlFormItem, IControlFormLabel -// { -// /// -// /// Returns or sets the label. -// /// -// public string Label { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a static text form item control. + /// + public class ControlFormItemStaticText : ControlFormItem, IControlFormLabel + { + /// + /// Returns or sets the label. + /// + public string Label { get; set; } -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlFormItemStaticText(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlFormItemStaticText(string id = null) + : base(id) + { + } -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public override void Initialize(RenderContextForm context) -// { -// } + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public override void Initialize(IRenderControlFormContext renderContext) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(RenderContextForm context) -// { -// var c = new List -// { -// "form-control-static" -// }; + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlFormContext renderContext) + { + var c = new List + { + "form-control-static" + }; -// var html = new HtmlElementTextContentP() -// { -// Text = I18N.Translate(context.Culture, Text), -// Class = Css.Concatenate(GetClasses()), -// Style = Style.Concatenate(GetStyles()), -// Role = Role -// }; + var html = new HtmlElementTextContentP() + { + Id = Id, + Text = I18N.Translate(renderContext.Request?.Culture, Text), + Class = Css.Concatenate(GetClasses()), + Style = Style.Concatenate(GetStyles()), + Role = Role + }; -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs index e6ee084d..582684a3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs @@ -1,205 +1,223 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlNavigation : Control -// { -// /// -// /// Returns or sets the layout. -// /// -// public TypeLayoutTab Layout -// { -// get => (TypeLayoutTab)GetProperty(TypeLayoutTab.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the horizontal arrangement. -// /// -// public new TypeHorizontalAlignmentTab HorizontalAlignment -// { -// get => (TypeHorizontalAlignmentTab)GetProperty(TypeHorizontalAlignmentTab.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets whether the tab tabs should be the same size. -// /// -// public TypeJustifiedTab Justified -// { -// get => (TypeJustifiedTab)GetProperty(TypeJustifiedTab.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the horizontal or vertical orientation. -// /// -// public TypeOrientationTab Orientation -// { -// get => (TypeOrientationTab)GetProperty(TypeOrientationTab.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the active color. -// /// -// public PropertyColorBackground ActiveColor { get; set; } = new PropertyColorBackground(); - -// /// -// /// Returns or sets the active text color. -// /// -// public PropertyColorText ActiveTextColor { get; set; } = new PropertyColorText(); - -// /// -// /// Returns or sets the link color. -// /// -// public PropertyColorText LinkColor { get; set; } = new PropertyColorText(); - -// /// -// /// Returns or sets the navigation items. -// /// -// public List Items { get; private set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlNavigation(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The navigation items. -// public ControlNavigation(params IControlNavigationItem[] items) -// : base(null) -// { -// Items.AddRange(items); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlNavigation(string id, IEnumerable content) -// : base(id) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlNavigation(IEnumerable content) -// : base(null) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// //ActiveColor = LayoutSchema.NavigationActiveBackground; -// //ActiveTextColor = LayoutSchema.NavigationActive; -// //LinkColor = LayoutSchema.NavigationLink; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var items = new List(); -// foreach (var item in Items) -// { -// var i = item.Render(context) as HtmlElement; - -// if (item is ControlNavigationItemLink link) -// { -// i.RemoveClass(link.TextColor?.ToClass()); -// i.RemoveStyle(link.TextColor?.ToStyle()); - -// i.AddClass -// ( -// Css.Concatenate -// ( -// "nav-link", -// link.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", -// link.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : LinkColor?.ToClass() -// ) -// ); - -// i.AddStyle -// ( -// Style.Concatenate -// ( -// link.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", -// link.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : LinkColor?.ToStyle() -// ) -// ); - - -// } -// else if (item is ControlNavigationItemDropdown dropdown) -// { -// i.RemoveClass(dropdown.TextColor?.ToClass()); -// i.RemoveStyle(dropdown.TextColor?.ToStyle()); - -// i.AddClass -// ( -// Css.Concatenate -// ( -// "nav-link", -// dropdown.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", -// dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : "" -// ) -// ); -// i.AddStyle -// ( -// Style.Concatenate -// ( -// dropdown.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", -// dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : "" -// ) -// ); -// } -// else -// { -// //i.AddClass(Css.Concatenate("nav-link")); -// } - -// items.Add(new HtmlElementTextContentLi(i) -// { -// Class = "nav-item" -// }); -// } - -// var html = new HtmlElementTextContentUl(items) -// { -// Id = Id, -// Class = Css.Concatenate("nav", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a navigation control. + /// + public class ControlNavigation : Control + { + private List _items = []; + + /// + /// Returns the navigation items. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the layout. + /// + public TypeLayoutTab Layout + { + get => (TypeLayoutTab)GetProperty(TypeLayoutTab.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the horizontal arrangement. + /// + public new TypeHorizontalAlignmentTab HorizontalAlignment + { + get => (TypeHorizontalAlignmentTab)GetProperty(TypeHorizontalAlignmentTab.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets whether the tab tabs should be the same size. + /// + public TypeJustifiedTab Justified + { + get => (TypeJustifiedTab)GetProperty(TypeJustifiedTab.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the horizontal or vertical orientation. + /// + public TypeOrientationTab Orientation + { + get => (TypeOrientationTab)GetProperty(TypeOrientationTab.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the active color. + /// + public PropertyColorBackground ActiveColor { get; set; } = new PropertyColorBackground(); + + /// + /// Returns or sets the active text color. + /// + public PropertyColorText ActiveTextColor { get; set; } = new PropertyColorText(); + + /// + /// Returns or sets the link color. + /// + public PropertyColorText LinkColor { get; set; } = new PropertyColorText(); + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The navigation items. + public ControlNavigation(string id = null, params IControlNavigationItem[] items) + : base(id) + { + _items.AddRange(items); + + //ActiveColor = LayoutSchema.NavigationActiveBackground; + //ActiveTextColor = LayoutSchema.NavigationActive; + //LinkColor = LayoutSchema.NavigationLink; + } + + /// + /// Adds one or more items to the content of the control. + /// + /// The items to add to the control. + /// + /// This method allows adding one or multiple items to the collection of + /// the control. + /// Example usage: + /// + /// var control = new ControlNavigation(); + /// var text1 = new ControlNavigationItemLink { Text = "A" }; + /// var text2 = new ControlNavigationItemLink { Text = "B" }; + /// control.Add(text1, text2); + /// + /// This method accepts any items that implements the interface. + /// + public virtual void Add(params IControlNavigationItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds one or more items to the content of the control. + /// + /// The items to add to the control. + /// + /// This method allows adding one or multiple items to the collection of + /// the control. + /// Example usage: + /// + /// var control = new ControlNavigation(); + /// var text1 = new ControlNavigationItemLink { Text = "A" }; + /// var text2 = new ControlNavigationItemLink { Text = "B" }; + /// control.Add(new List([text1, text2])); + /// + /// This method accepts any items that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _items.AddRange(controls); + } + + /// + /// Removes a item from the content of the control. + /// + /// The item to remove from the content. + /// + /// This method allows removing a specific item from the collection of + /// the control. + /// + public virtual void Remove(IControlNavigationItem item) + { + _items.Remove(item); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var items = new List(); + foreach (var item in Items) + { + var i = item.Render(renderContext) as HtmlElement; + + if (item is ControlNavigationItemLink link) + { + i.RemoveClass(link.TextColor?.ToClass()); + i.RemoveStyle(link.TextColor?.ToStyle()); + + i.AddClass + ( + Css.Concatenate + ( + "nav-link", + link.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", + link.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : LinkColor?.ToClass() + ) + ); + + i.AddStyle + ( + Style.Concatenate + ( + link.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", + link.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : LinkColor?.ToStyle() + ) + ); + + + } + else if (item is ControlNavigationItemDropdown dropdown) + { + i.RemoveClass(dropdown.TextColor?.ToClass()); + i.RemoveStyle(dropdown.TextColor?.ToStyle()); + + i.AddClass + ( + Css.Concatenate + ( + "nav-link", + dropdown.Active == TypeActive.Active ? ActiveColor?.ToClass() : "", + dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToClass() : "" + ) + ); + i.AddStyle + ( + Style.Concatenate + ( + dropdown.Active == TypeActive.Active ? ActiveColor?.ToStyle() : "", + dropdown.Active == TypeActive.Active ? ActiveTextColor?.ToStyle() : "" + ) + ); + } + else + { + //i.AddClass(Css.Concatenate("nav-link")); + } + + items.Add(new HtmlElementTextContentLi(i) + { + Class = "nav-item" + }); + } + + var html = new HtmlElementTextContentUl(items.ToArray()) + { + Id = Id, + Class = Css.Concatenate("nav", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs index a6d69a17..c204d59b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs @@ -1,27 +1,31 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlNavigationItemDropdown : ControlDropdown, IControlNavigationItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlNavigationItemDropdown(string id = null) -// : base(id) -// { -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a navigation item dropdown control. + /// + public class ControlNavigationItemDropdown : ControlDropdown, IControlNavigationItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The items to be added to the dropdown. + public ControlNavigationItemDropdown(string id = null, params IControlDropdownItem[] items) + : base(id, items) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return base.Render(context); -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return base.Render(renderContext); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs index b6007711..4c173925 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs @@ -1,50 +1,42 @@ -ο»Ώ//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlNavigationItemHeader : Control, IControlNavigationItem -// { -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a navigation item header control. + /// + public class ControlNavigationItemHeader : Control, IControlNavigationItem + { + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlNavigationItemHeader(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlNavigationItemHeader(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The text. -// public ControlNavigationItemHeader(string id, string text) -// : base(id) -// { -// Text = text; -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(context.Culture, Text))) -// { -// Id = Id, -// Class = Css.Concatenate("dropdown-header", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))) + { + Id = Id, + Class = Css.Concatenate("dropdown-header", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index ff843800..5de2e9b5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -1,125 +1,126 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. - /// - public class ControlPanel : Control - { - private readonly List _content = []; - - /// - /// Returns the content of the panel. - /// - /// - /// The content property holds a collection of controls that represent the visual and interactive elements - /// within this container. - /// - public IEnumerable Content => _content; - - /// - /// Returns or sets the arrangement of the content. - /// - public TypeDirection Direction - { - get => (TypeDirection)GetProperty(TypeDirection.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Fixed or full-width adjustment. - /// - public TypePanelContainer Fluid - { - get => (TypePanelContainer)GetProperty(TypePanelContainer.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The child controls to be added to the panel. - public ControlPanel(string id = null, params IControl[] controls) - : base(id) - { - _content.AddRange(controls.Where(x => x != null)); - } - - /// - /// Adds one or more controls to the content of the control panel. - /// - /// The controls to add to the content. - /// - /// This method allows adding one or multiple controls to the collection of - /// the control panel. It is useful for dynamically constructing the user interface by appending - /// various controls to the panel's content. - /// Example usage: - /// - /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "A" }; - /// var text2 = new ControlText { Text = "B" }; - /// panel.Add(text1, text2); - /// - /// This method accepts any control that implements the interface. - /// - public virtual void Add(params IControl[] controls) - { - _content.AddRange(controls); - } - - /// - /// Adds one or more controls to the content of the control panel. - /// - /// The controls to add to the content. - /// - /// This method allows adding one or multiple controls to the collection of - /// the control panel. It is useful for dynamically constructing the user interface by appending - /// various controls to the panel's content. - /// Example usage: - /// - /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "A" }; - /// var text2 = new ControlText { Text = "B" }; - /// panel.Add(new List([text1, text2])); - /// - /// This method accepts any control that implements the interface. - /// - public virtual void Add(IEnumerable controls) - { - _content.AddRange(controls); - } - - /// - /// Removes a control from the content of the control panel. - /// - /// The control to remove from the content. - /// - /// This method allows removing a specific control from the collection of - /// the control panel. - /// - public virtual void Remove(Control control) - { - _content.Remove(control); - } - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) - { - return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. + /// + public class ControlPanel : Control + { + private readonly List _content = []; + + /// + /// Returns the content of the panel. + /// + /// + /// The content property holds a collection of controls that represent the visual and interactive elements + /// within this container. + /// + public IEnumerable Content => _content; + + /// + /// Returns or sets the arrangement of the content. + /// + public TypeDirection Direction + { + get => (TypeDirection)GetProperty(TypeDirection.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Fixed or full-width adjustment. + /// + public TypePanelContainer Fluid + { + get => (TypePanelContainer)GetProperty(TypePanelContainer.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel. + public ControlPanel(string id = null, params IControl[] controls) + : base(id) + { + _content.AddRange(controls.Where(x => x != null)); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _content.AddRange(controls); + } + + /// + /// Removes a control from the content of the control panel. + /// + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the control panel. + /// + public virtual void Remove(Control control) + { + _content.Remove(control); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs index 30d42a5d..85c64a7c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs @@ -1,66 +1,39 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelFooter : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelFooter(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a footer control panel that can contain multiple child controls and + /// manage their layout and rendering. + /// + public class ControlPanelFooter : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlPanelFooter(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanelFooter(string id, params Control[] content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanelFooter(string id, List content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Content.Add(new ControlPanel(new ControlLine())); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementSectionFooter(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementSectionFooter(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs index 96d4d687..d5a84689 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs @@ -1,38 +1,41 @@ -ο»Ώ//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelMain : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelMain(string id = null) -// : base(id) -// { -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents the main control panel that can contain multiple child controls and manage + /// their layout and rendering. + /// + public class ControlPanelMain : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlPanelMain(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementSectionMain() -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementSectionMain(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; -// html.Elements.AddRange(from x in Content select x?.Render(context)); - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs index f5f78004..bf7803ec 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs @@ -1,161 +1,189 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; -//using WebExpress.WebCore.WebUri; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Two panels that can be resized by a variable splitter. -// /// -// public class ControlPanelSplit : Control -// { -// /// -// /// Returns or sets whether the splitter is horziontal or vertically oriented. -// /// -// public TypeOrientationSplit Orientation { get; set; } - -// /// -// /// Returns or sets the color of the splitter. -// /// -// public PropertyColorBackground SplitterColor { get; set; } = new PropertyColorBackground(TypeColorBackground.Light); - -// /// -// /// Returns or sets the width of the splitter. -// /// -// public int SplitterSize { get; set; } = 6; - -// /// -// /// Returns the left or top panel in the ControlPanelSplit. -// /// -// public List Panel1 { get; } = new List(); - -// /// -// /// Returns or sets the minimum size of the left or top area in the ControlPanelSplit. -// /// -// public int Panel1MinSize { get; set; } - -// /// -// /// Returns or sets the initial size of the left or top area in the ControlPanelSplit in %. -// /// -// public int Panel1InitialSize { get; set; } = -1; - -// /// -// /// Returns the right or bottom pane in the ControlPanelSplit. -// /// -// public List Panel2 { get; } = new List(); - -// /// -// /// Returns or sets the minimum size of the right or bottom area in the ControlPanelSplit. -// /// -// public int Panel2MinSize { get; set; } - -// /// -// /// Returns or sets the initial size of the right or bottom area in the ControlPanelSplit in %. -// /// -// public int Panel2InitialSize { get; set; } = -1; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelSplit(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// Left or top panel controls. -// /// Right or bottom panel controls. -// public ControlPanelSplit(string id, Control[] panel1, Control[] panel2) -// : base(id) -// { -// Panel1.AddRange(panel1); -// Panel2.AddRange(panel2); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// Left or top panel controls. -// /// Right or bottom panel controls. -// public ControlPanelSplit(Control[] panel1, Control[] panel2) -// : this(null, panel1, panel2) -// { -// } - -// /// -// /// Initializes the form element. -// /// -// /// The context in which the control is rendered. -// public void Initialize(RenderContext context) -// { -// var contextPath = context?.PageContext?.ApplicationContext?.ContextPath; -// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/split.min.js")); - -// Border = new PropertyBorder(true); - -// var init1 = 0; -// var init2 = 0; - -// if (Panel1InitialSize < 0 && Panel2InitialSize < 0) -// { -// init1 = init2 = 50; -// } -// else if (Panel1InitialSize < 0) -// { -// init1 = 100 - Panel2InitialSize; -// init2 = Panel2InitialSize; -// } -// else if (Panel2InitialSize < 0) -// { -// init1 = Panel1InitialSize; -// init2 = 100 - Panel1InitialSize; -// } - -// context.VisualTree.AddScript -// ( -// Id, @"Split(['#" + Id + "-p1', '#" + Id + @"-p2'], { -// sizes: [" + init1 + "," + init2 + @"], -// minSize: [" + Panel1MinSize + "," + Panel2MinSize + @"], -// direction: '" + Orientation.ToString().ToLower() + @"', -// gutter: function (index, direction) -// { -// var gutter = document.createElement('div'); -// gutter.className = 'splitter splitter-' + direction + ' " + SplitterColor.ToClass() + @"'; -// gutter.style = '" + SplitterColor.ToStyle() + @"'; -// return gutter; -// }, -// gutterSize: " + SplitterSize + @", -// });" -// ); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// Initialize(context); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate(Orientation == TypeOrientationSplit.Horizontal ? "d-flex split" : "split", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// html.Elements.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(context))) { Id = $"{Id}-p1" }); -// html.Elements.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(context))) { Id = $"{Id}-p2" }); - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control that splits the available space into two resizable panels. + /// + public class ControlPanelSplit : Control + { + private readonly List _panel1 = []; + private readonly List _panel2 = []; + + /// + /// Returns the left or top panel in the ControlPanelSplit. + /// + public IEnumerable Panel1 => _panel1; + + /// + /// Returns the right or bottom pane in the ControlPanelSplit. + /// + public IEnumerable Panel2 => _panel2; + + /// + /// Returns or sets whether the splitter is horziontal or vertically oriented. + /// + public TypeOrientationSplit Orientation { get; set; } + + /// + /// Returns or sets the color of the splitter. + /// + public PropertyColorBackground SplitterColor { get; set; } = new PropertyColorBackground(TypeColorBackground.Light); + + /// + /// Returns or sets the width of the splitter. + /// + public int SplitterSize { get; set; } = 6; + + /// + /// Returns or sets the minimum size of the left or top area in the ControlPanelSplit. + /// + public int Panel1MinSize { get; set; } + + /// + /// Returns or sets the initial size of the left or top area in the ControlPanelSplit in %. + /// + public int Panel1InitialSize { get; set; } = -1; + + /// + /// Returns or sets the minimum size of the right or bottom area in the ControlPanelSplit. + /// + public int Panel2MinSize { get; set; } + + /// + /// Returns or sets the initial size of the right or bottom area in the ControlPanelSplit in %. + /// + public int Panel2InitialSize { get; set; } = -1; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlPanelSplit(string id = null) + : base(id) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// Left or top panel controls. + /// Right or bottom panel controls. + public ControlPanelSplit(string id, IControl[] panel1, IControl[] panel2) + : base(id) + { + _panel1.AddRange(panel1); + _panel2.AddRange(panel2); + } + + /// + /// Adds controls to the left or top panel. + /// + /// The controls to add. + public void AddPanel1(params IControl[] controls) + { + _panel1.AddRange(controls); + } + + /// + /// Removes a control from the left or top panel. + /// + /// The control to remove. + public void RemovePanel1(IControl control) + { + _panel1.Remove(control); + } + + /// + /// Adds controls to the right or bottom panel. + /// + /// The controls to add. + public void AddPanel2(params IControl[] controls) + { + _panel2.AddRange(controls); + } + + /// + /// Removes a control from the right or bottom panel. + /// + /// The control to remove. + public void RemovePanel2(IControl control) + { + _panel2.Remove(control); + } + + /// + /// Initializes the form element. + /// + /// The context in which the control is rendered. + public virtual void Initialize(IRenderControlContext renderContext) + { + var contextPath = renderContext?.PageContext?.ApplicationContext?.ContextPath; + //renderContext.AddHeaderScriptLink(UriResource.Combine(contextPath, "/assets/js/split.min.js")); + + Border = new PropertyBorder(true); + + var init1 = 0; + var init2 = 0; + + if (Panel1InitialSize < 0 && Panel2InitialSize < 0) + { + init1 = init2 = 50; + } + else if (Panel1InitialSize < 0) + { + init1 = 100 - Panel2InitialSize; + init2 = Panel2InitialSize; + } + else if (Panel2InitialSize < 0) + { + init1 = Panel1InitialSize; + init2 = 100 - Panel1InitialSize; + } + + renderContext.AddScript + ( + Id, @"Split(['#" + Id + "-p1', '#" + Id + @"-p2'], { + sizes: [" + init1 + "," + init2 + @"], + minSize: [" + Panel1MinSize + "," + Panel2MinSize + @"], + direction: '" + Orientation.ToString().ToLower() + @"', + gutter: function (index, direction) + { + var gutter = document.createElement('div'); + gutter.className = 'splitter splitter-' + direction + ' " + SplitterColor.ToClass() + @"'; + gutter.style = '" + SplitterColor.ToStyle() + @"'; + return gutter; + }, + gutterSize: " + SplitterSize + @", + });" + ); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + Initialize(renderContext); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate(Orientation == TypeOrientationSplit.Horizontal ? "d-flex split" : "split", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + html.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(renderContext)).ToArray()) { Id = $"{Id}-p1" }); + html.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(renderContext)).ToArray()) { Id = $"{Id}-p2" }); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/IFormValidation.cs b/src/WebExpress.WebUI/WebControl/IFormValidation.cs index fba2cce5..cc78f5ee 100644 --- a/src/WebExpress.WebUI/WebControl/IFormValidation.cs +++ b/src/WebExpress.WebUI/WebControl/IFormValidation.cs @@ -15,7 +15,7 @@ public interface IFormValidation /// /// Determines whether the inputs are valid. /// - ICollection ValidationResults { get; } + IEnumerable ValidationResults { get; } /// /// Returns the most serious validation result. From 86cfb74fafc7f0d80fa7c2ba760639e66543d93b Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Thu, 26 Dec 2024 21:53:15 +0100 Subject: [PATCH 28/59] refactoring and add tests --- .../WebControl/UnitTestControlBreadcrumb.cs | 129 ++++++ .../WebControl/UnitTestControlList.cs | 8 +- .../WebControl/UnitTestControlPanel.cs | 28 ++ .../WebControl/UnitTestControlPanelCallout.cs | 104 +++++ .../WebControl/UnitTestControlPanelCenter.cs | 132 ++++++ .../WebControl/UnitTestControlPanelNavbar.cs | 132 ++++++ .../WebControl/UnitTestControlPanelToast.cs | 132 ++++++ .../WebControl/UnitTestControlSplitButton.cs | 57 +-- .../UnitTestControlSplitButtonLink.cs | 213 +++++++++ .../UnitTestControlToolBarItemSeperator.cs | 33 ++ .../WebControl/UnitTestControlToolbar.cs | 80 ++++ .../UnitTestControlToolbarItemButton.cs | 260 +++++++++++ .../WebControl/ControlBreadcrumb.cs | 310 ++++++------- .../WebControl/ControlList.cs | 287 ++++++------ .../WebControl/ControlPanelCallout.cs | 137 +++--- .../WebControl/ControlPanelCenter.cs | 99 ++-- .../WebControl/ControlPanelNavbar.cs | 101 ++-- .../WebControl/ControlPanelToast.cs | 33 +- .../WebControl/ControlSplitButton.cs | 436 +++++++++--------- .../WebControl/ControlSplitButtonLink.cs | 367 ++++++--------- .../WebControl/ControlToolbar.cs | 294 ++++++------ .../WebControl/ControlToolbarItemButton.cs | 46 +- .../WebControl/ControlToolbarItemDivider.cs | 17 + .../WebControl/ControlToolbarItemSeperator.cs | 15 - .../WebControl/IControlButton.cs | 5 +- .../WebControl/IControlFormLabel.cs | 3 + .../WebControl/IControlLink.cs | 3 + .../WebControl/IControlNavigationItem.cs | 3 + .../WebControl/IControlSplitButtonItem.cs | 3 + .../WebControl/IControlToolbarItem.cs | 5 +- src/WebExpress.WebUI/WebControl/IProperty.cs | 2 +- 31 files changed, 2313 insertions(+), 1161 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs create mode 100644 src/WebExpress.WebUI/WebControl/ControlToolbarItemDivider.cs delete mode 100644 src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs new file mode 100644 index 00000000..2ce72d3e --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs @@ -0,0 +1,129 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the breadcrumb control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlBreadcrumb + { + /// + /// Tests the id property of the breadcrumb control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                          ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                            ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the breadcrumb control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                              ")] + [InlineData("http://example.com", @"
                                                                                                                                                                                                                                                                ")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb { Uri = uri }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the empty name property of the breadcrumb control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                  ")] + [InlineData("Home", @"
                                                                                                                                                                                                                                                                    ")] + public void EmptyName(string emptyName, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb { EmptyName = emptyName }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the breadcrumb control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"
                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeSizeButton.Small, @"
                                                                                                                                                                                                                                                                        ")] + [InlineData(TypeSizeButton.Large, @"
                                                                                                                                                                                                                                                                          ")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb { Size = size }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the prefix property of the breadcrumb control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                            ")] + [InlineData("Prefix", @"
                                                                                                                                                                                                                                                                              ")] + public void Prefix(string prefix, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb { Prefix = prefix }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the take last property of the breadcrumb control. + /// + [Theory] + [InlineData((ushort)5, @"
                                                                                                                                                                                                                                                                                ")] + [InlineData(3, @"
                                                                                                                                                                                                                                                                                  ")] + public void TakeLast(ushort takeLast, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBreadcrumb { TakeLast = takeLast }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs index e9e31264..81b8e828 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs @@ -7,7 +7,7 @@ namespace WebExpress.WebUI.Test.WebControl /// Tests the list control. ///
                                                                                                                                                                                                                                                                                  [Collection("NonParallelTests")] - public class UnitTestControlList : IClassFixture + public class UnitTestControlList { /// /// Tests the id property of the list control. @@ -28,7 +28,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -81,7 +81,7 @@ public void Layout(TypeLayoutList layout, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -99,7 +99,7 @@ public void Add(IEnumerable items, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs index e07b9376..753f83fe 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -30,6 +30,34 @@ public void Id(string id, string expected) AssertExtensions.EqualWithPlaceholders(expected, html); } + /// + /// Tests the background color property of the panel control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                  ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanel() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + /// /// Tests the direction property of the panel control. /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs new file mode 100644 index 00000000..d34051bc --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs @@ -0,0 +1,104 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel callout control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelCallout + { + /// + /// Tests the id property of the panel callout control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCallout(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the panel callout control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCallout() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the panel callout control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                  ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCallout() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the panel callout control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                  ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelCallout(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs new file mode 100644 index 00000000..081aa352 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs @@ -0,0 +1,132 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the center panel control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelCenter + { + /// + /// Tests the id property of the center panel control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCenter(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the center panel control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                  ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCenter() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the center panel control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCenter() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the center panel control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                  ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelCenter() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the center panel control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                  ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelCenter(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs new file mode 100644 index 00000000..54ad24b0 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs @@ -0,0 +1,132 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the navbar control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelNavbar + { + /// + /// Tests the id property of the navbar control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelNavbar(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the navbar control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelNavbar() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the navbar control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"")] + [InlineData(TypeDirection.Vertical, @"")] + [InlineData(TypeDirection.VerticalReverse, @"")] + [InlineData(TypeDirection.Horizontal, @"")] + [InlineData(TypeDirection.HorizontalReverse, @"")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelNavbar() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the navbar control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"")] + [InlineData(TypePanelContainer.Default, @"")] + [InlineData(TypePanelContainer.Fluid, @"")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelNavbar() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the navbar control. + /// + [Theory] + [InlineData(typeof(ControlText), @"")] + [InlineData(typeof(ControlLink), @"")] + [InlineData(typeof(ControlImage), @"")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelNavbar(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs new file mode 100644 index 00000000..2a1c16b9 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs @@ -0,0 +1,132 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the toast control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelToast + { + /// + /// Tests the id property of the toast control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                  ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelToast(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the toast control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                  ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelToast() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the toast control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                  ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelToast() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the toast control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                  ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelToast() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add child function of the toast control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                  ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                  ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelToast(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs index 3a380ef8..067d2e3a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -180,33 +180,34 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - //UnitTestControlFixture.CreateAndRegisterComponentHubMock(); - //var context = UnitTestControlFixture.CrerateRenderContextMock(); - //var control1 = new ControlSplitButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); - //var control2 = new ControlSplitButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); - //var control3 = new ControlSplitButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - //var control4 = new ControlSplitButton(null); - //var control5 = new ControlSplitButton(null); - //var control6 = new ControlSplitButton(null); - - //// test execution - //control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); - //control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); - //control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - - //var html1 = control1.Render(context); - //var html2 = control2.Render(context); - //var html3 = control2.Render(context); - //var html4 = control1.Render(context); - //var html5 = control2.Render(context); - //var html6 = control2.Render(context); - - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html1.Trim()); - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html2.Trim()); - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html3.Trim()); - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html4.Trim()); - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html5.Trim()); - //AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                  *
                                                                                                                                                                                                                                                                                  ", html6.Trim()); + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlSplitButton(null, new ControlSplitButtonItemLink() { Text = "abc" }); + var control2 = new ControlSplitButton(null, [new ControlSplitButtonItemLink() { Text = "abc" }]); + var control3 = new ControlSplitButton(null, new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); + var control4 = new ControlSplitButton(null); + var control5 = new ControlSplitButton(null); + var control6 = new ControlSplitButton(null); + + // test execution + control4.Add(new ControlSplitButtonItemLink() { Text = "abc" }); + control5.Add([new ControlSplitButtonItemLink() { Text = "abc" }]); + control6.Add(new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + var html4 = control1.Render(context); + var html5 = control2.Render(context); + var html6 = control2.Render(context); + + var expected = @"
                                                                                                                                                                                                                                                                                  *abc*
                                                                                                                                                                                                                                                                                  "; + AssertExtensions.EqualWithPlaceholders(expected, html1); + AssertExtensions.EqualWithPlaceholders(expected, html2); + AssertExtensions.EqualWithPlaceholders(expected, html3); + AssertExtensions.EqualWithPlaceholders(expected, html4); + AssertExtensions.EqualWithPlaceholders(expected, html5); + AssertExtensions.EqualWithPlaceholders(expected, html6); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs new file mode 100644 index 00000000..654a611a --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs @@ -0,0 +1,213 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the split button link control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlSplitButtonLink + { + /// + /// Tests the id property of the split button link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                    ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the split button link control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the split button link control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeSizeButton.Small, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeSizeButton.Large, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + Size = size + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the backgroundcolor property of the split button link control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorButton.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorButton.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorButton.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorButton.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorButton.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the split button link control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, TypeColorButton.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + Outline = outline, + BackgroundColor = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the block property of the split button link control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeBlockButton.Block, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + Block = block + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the split button link control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlSplitButtonLink() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the split button link control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlSplitButtonLink(null, new ControlSplitButtonItemLink() { Text = "abc" }); + var control2 = new ControlSplitButtonLink(null, [new ControlSplitButtonItemLink() { Text = "abc" }]); + var control3 = new ControlSplitButtonLink(null, new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); + var control4 = new ControlSplitButtonLink(null); + var control5 = new ControlSplitButtonLink(null); + var control6 = new ControlSplitButtonLink(null); + + // test execution + control4.Add(new ControlSplitButtonItemLink() { Text = "abc" }); + control5.Add([new ControlSplitButtonItemLink() { Text = "abc" }]); + control6.Add(new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control2.Render(context); + var html4 = control1.Render(context); + var html5 = control2.Render(context); + var html6 = control2.Render(context); + + var expected = @""; + AssertExtensions.EqualWithPlaceholders(expected, html1); + AssertExtensions.EqualWithPlaceholders(expected, html2); + AssertExtensions.EqualWithPlaceholders(expected, html3); + AssertExtensions.EqualWithPlaceholders(expected, html4); + AssertExtensions.EqualWithPlaceholders(expected, html5); + AssertExtensions.EqualWithPlaceholders(expected, html6); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs new file mode 100644 index 00000000..5ac6c849 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs @@ -0,0 +1,33 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the toolbar item divider control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlToolBarItemSeperator + { + /// + /// Tests the id property of the toolbar item divider control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemDivider(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs new file mode 100644 index 00000000..b18edc66 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs @@ -0,0 +1,80 @@ + +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the toolbar control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlToolbar + { + /// + /// Tests the id property of the toolbar control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + [InlineData("03C6031F-04A9-451F-B817-EBD6D32F8B0C", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbar(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the toolbar control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbar() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the toolbar control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbar(null, new ControlToolbarItemButton() { Text = "abc" }); + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs new file mode 100644 index 00000000..35b3d3db --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs @@ -0,0 +1,260 @@ +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the toolbar item button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlToolbarItemButton + { + /// + /// Tests the id property of the toolbar item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the toolbar item button control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the toolbar item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.WebUI:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the tooltip property of the toolbar item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + [InlineData("webexpress.WebUI:plugin.name", @"")] + public void Tooltip(string tooltip, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton() + { + Tooltip = tooltip, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the toolbar item button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the active property of the toolbar item button control. + /// + [Theory] + [InlineData(TypeActive.None, @"")] + [InlineData(TypeActive.Active, @"")] + [InlineData(TypeActive.Disabled, @"")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlToolbarItemButton() + { + Active = active + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the toolbar item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("/a", @"")] + [InlineData("/a/b", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Uri = uri, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the title property of the toolbar item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("a", @"")] + [InlineData("b", @"")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Title = title, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the target property of the toolbar item button control. + /// + [Theory] + [InlineData(TypeTarget.None, @"")] + [InlineData(TypeTarget.Blank, @"")] + [InlineData(TypeTarget.Self, @"")] + [InlineData(TypeTarget.Parent, @"")] + [InlineData(TypeTarget.Framename, @"")] + public void Target(TypeTarget target, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlLink() + { + Target = target, + }; + + // test execution + var html = control.Render(context); + + Assert.Equal(expected, html.Trim()); + } + + /// + /// Tests the add function of the toolbar item button control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlLink(null); + var control5 = new ControlLink(null); + var control6 = new ControlLink(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); + + Assert.Equal(@"", html1.Trim()); + Assert.Equal(@"", html2.Trim()); + Assert.Equal(@"", html3.Trim()); + Assert.Equal(@"", html4.Trim()); + Assert.Equal(@"", html5.Trim()); + Assert.Equal(@"", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs index 68810bb3..782be6c6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs @@ -1,162 +1,148 @@ -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlBreadcrumb : Control -// { -// /// -// /// Return or sets the uri. -// /// -// public string Uri { get; set; } - -// /// -// /// Return or sets the root element. -// /// -// public string EmptyName { get; set; } - -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeButton Size -// { -// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Return or sets a prefix, which is statically displayed in front of the links. -// /// -// public string Prefix { get; set; } - -// /// -// /// Return or sets how many links to display. It will be truncated at the beginning of the link chain. -// /// -// public ushort TakeLast { get; set; } = ushort.MaxValue; - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlBreadcrumb(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// Der Verzeichnispfad -// public ControlBreadcrumb(string id, string uri) -// : base(id) -// { -// Uri = uri; -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Size = TypeSizeButton.Small; -// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Light); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentOl() -// { -// Class = Css.Concatenate("breadcrumb bg-light ps-2", GetClasses()), -// Style = GetStyles(), -// }; - -// if (!string.IsNullOrWhiteSpace(Prefix)) -// { -// html.Elements.Add -// ( -// new HtmlElementTextContentLi -// ( -// new HtmlElementTextContentDiv -// ( -// new HtmlText(I18N.Translate(context.Culture, Prefix)) -// ) -// { -// Class = "me-2 text-muted" -// } -// ) -// ); -// } - -// foreach (var part in context.Uri.PathSegments) -// { -// if (part.Display != null) -// { -// var display = part.GetDisplay(context.Culture); -// var href = part.ToString(); - -// html.Elements.Add -// ( -// new HtmlElementTextContentLi -// ( -// //new ControlIcon(Page) -// //{ -// // Icon = path.Icon -// //}.ToHtml(), -// new HtmlElementTextSemanticsA(display) -// { -// Href = href -// } -// ) -// { -// Class = "breadcrumb-item" -// } -// ); -// } -// } - -// //var takeLast = Math.Min(TakeLast, resourceUri.Path.Count); -// //var from = resourceUri.Path.Count - takeLast; - -// //for (int i = from + 1; i < resourceUri.Path.Count + 1; i++) -// //{ -// // var path = resourceUri.Take(i); - -// // if (path.Display != null) -// // { -// // var display = I18N(context.Culture, path.Display); -// // var href = path.ToString(); - -// // html.Elements.Add -// // ( -// // new HtmlElementTextContentLi -// // ( -// // //new ControlIcon(Page) -// // //{ -// // // Icon = path.Icon -// // //}.ToHtml(), -// // new HtmlElementTextSemanticsA(display) -// // { -// // Href = href, -// // Class = "link" -// // } -// // ) -// // { -// // Class = "breadcrumb-item" -// // } -// // ); -// // } -// //} -// //} - -// return html; -// } -// } -//} +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a breadcrumb control that displays a list of links indicating the current + /// page's location within a navigational hierarchy. + /// + public class ControlBreadcrumb : Control + { + /// + /// Return or sets the uri. + /// + public string Uri { get; set; } + + /// + /// Returns or sets the name to display when the breadcrumb is empty. + /// + public string EmptyName { get; set; } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Return or sets a prefix, which is statically displayed in front of the links. + /// + public string Prefix { get; set; } + + /// + /// Return or sets how many links to display. It will be truncated at the beginning of the link chain. + /// + public ushort TakeLast { get; set; } = ushort.MaxValue; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlBreadcrumb(string id = null) + : base(id) + { + Size = TypeSizeButton.Small; + BackgroundColor = new PropertyColorBackground(TypeColorBackground.Light); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentOl() + { + Id = Id, + Class = Css.Concatenate("breadcrumb bg-light ps-2", GetClasses()), + Style = GetStyles(), + }; + + if (!string.IsNullOrWhiteSpace(Prefix)) + { + html.Elements.Add + ( + new HtmlElementTextContentLi + ( + new HtmlElementTextContentDiv + ( + new HtmlText(I18N.Translate(renderContext.Request?.Culture, Prefix)) + ) + { + Class = "me-2 text-muted" + } + ) + ); + } + + foreach (var part in renderContext.Request?.Uri.PathSegments) + { + if (part.Display != null) + { + var display = part.GetDisplay(renderContext.Request?.Culture); + var href = part.ToString(); + + html.Elements.Add + ( + new HtmlElementTextContentLi + ( + //new ControlIcon(Page) + //{ + // Icon = path.Icon + //}.ToHtml(), + new HtmlElementTextSemanticsA(display) + { + Href = href + } + ) + { + Class = "breadcrumb-item" + } + ); + } + } + + //var takeLast = Math.Min(TakeLast, resourceUri.Path.Count); + //var from = resourceUri.Path.Count - takeLast; + + //for (int i = from + 1; i < resourceUri.Path.Count + 1; i++) + //{ + // var path = resourceUri.Take(i); + + // if (path.Display != null) + // { + // var display = I18N(context.Culture, path.Display); + // var href = path.ToString(); + + // html.Elements.Add + // ( + // new HtmlElementTextContentLi + // ( + // //new ControlIcon(Page) + // //{ + // // Icon = path.Icon + // //}.ToHtml(), + // new HtmlElementTextSemanticsA(display) + // { + // Href = href, + // Class = "link" + // } + // ) + // { + // Class = "breadcrumb-item" + // } + // ); + // } + //} + //} + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index b5b10c16..8bb2d1b1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -1,143 +1,144 @@ -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a control list that can contain multiple control list items. - /// - public class ControlList : Control - { - private readonly List _items = []; - - /// - /// Returns the list entries. - /// - public IEnumerable Items => _items; - - /// - /// Returns or sets the layout. - /// - public TypeLayoutList Layout - { - get => (TypeLayoutList)GetProperty(TypeLayoutList.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The list entries. - public ControlList(string id = null, params ControlListItem[] items) - : base(id) - { - _items.AddRange(items); - } - - /// - /// Adds a collection of list entries to the existing items. - /// - /// The list entries to add. - /// - /// This method appends the specified collection of instances to the - /// current list of items. It ensures that the new items are concatenated with the existing ones, - /// maintaining the order of addition. - /// Example usage: - /// - /// var list = new ControlList(); - /// var item1 = new ControlListItem { Text = "Item 1" }; - /// var item2 = new ControlListItem { Text = "Item 2" }; - /// list.Add(item1, item2); - /// - /// This method accepts any item that derives from . - /// - public void Add(params ControlListItem[] items) - { - _items.AddRange(items); - } - - /// - /// Adds a collection of list entries to the existing items. - /// - /// The list entries to add. - /// - /// This method appends the specified collection of instances to the - /// current list of items. It ensures that the new items are concatenated with the existing ones, - /// maintaining the order of addition. - /// Example usage: - /// - /// var list = new ControlList(); - /// var item1 = new ControlListItem { Text = "Item 1" }; - /// var item2 = new ControlListItem { Text = "Item 2" }; - /// list.Add(new List([ item1, item2 ])); - /// - /// This method accepts any item that derives from . - /// - public void Add(IEnumerable items) - { - _items.AddRange(items); - } - - /// - /// Removes a specified list entry from the existing items. - /// - /// The list entry to remove. - /// - /// This method removes the specified instance from the - /// current list of items. If the item does not exist in the list, the method does nothing. - /// Example usage: - /// - /// var list = new ControlList(); - /// var item1 = new ControlListItem { Text = "Item 1" }; - /// list.Add(item1); - /// list.Remove(item1); - /// - /// This method accepts any item that derives from . - /// - public void Remove(ControlListItem item) - { - _items.Remove(item); - } - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// - public override IHtmlNode Render(IRenderControlContext renderContext) - { - return Render(renderContext, Items); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// The list entries. - /// An HTML node representing the rendered control. - public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) - { - var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); - switch (Layout) - { - case TypeLayoutList.Horizontal: - case TypeLayoutList.Flush: - case TypeLayoutList.Group: - li.ForEach(x => x.AddClass("list-group-item")); - break; - } - - var html = new HtmlElementTextContentUl(li.ToArray()) - { - Id = Id, - Class = Css.Concatenate("", GetClasses()), - Style = GetStyles(), - Role = Role - }; - - return html; - } - } -} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control list that can contain multiple control list items. + /// + public class ControlList : Control + { + private readonly List _items = []; + + /// + /// Returns the list entries. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the layout. + /// + public TypeLayoutList Layout + { + get => (TypeLayoutList)GetProperty(TypeLayoutList.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The list entries. + public ControlList(string id = null, params ControlListItem[] items) + : base(id) + { + _items.AddRange(items); + } + + /// + /// Adds a collection of list entries to the existing items. + /// + /// The list entries to add. + /// + /// This method appends the specified collection of instances to the + /// current list of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// var item2 = new ControlListItem { Text = "Item 2" }; + /// list.Add(item1, item2); + /// + /// This method accepts any item that derives from . + /// + public void Add(params ControlListItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds a collection of list entries to the existing items. + /// + /// The list entries to add. + /// + /// This method appends the specified collection of instances to the + /// current list of items. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// var item2 = new ControlListItem { Text = "Item 2" }; + /// list.Add(new List([ item1, item2 ])); + /// + /// This method accepts any item that derives from . + /// + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Removes a specified list entry from the existing items. + /// + /// The list entry to remove. + /// + /// This method removes the specified instance from the + /// current list of items. If the item does not exist in the list, the method does nothing. + /// Example usage: + /// + /// var list = new ControlList(); + /// var item1 = new ControlListItem { Text = "Item 1" }; + /// list.Add(item1); + /// list.Remove(item1); + /// + /// This method accepts any item that derives from . + /// + public void Remove(ControlListItem item) + { + _items.Remove(item); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return Render(renderContext, Items); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// The list entries. + /// An HTML node representing the rendered control. + public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + { + var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); + switch (Layout) + { + case TypeLayoutList.Horizontal: + case TypeLayoutList.Flush: + case TypeLayoutList.Group: + li.ForEach(x => x.AddClass("list-group-item")); + break; + } + + var html = new HtmlElementTextContentUl(li.ToArray()) + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs index 5d48dfce..dbdc98a3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs @@ -1,84 +1,67 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelCallout : ControlPanel -// { -// /// -// /// Delivers or sets the title. -// /// -// public string Title { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a callout panel control that can contain multiple child controls. + /// + public class ControlPanelCallout : ControlPanel + { + /// + /// Returns or sets the title. + /// + public string Title { get; set; } -// /// -// /// Returns or sets the color. -// /// -// public PropertyColorCallout Color -// { -// get => (PropertyColorCallout)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); -// } + /// + /// Returns or sets the color. + /// + public PropertyColorCallout Color + { + get => (PropertyColorCallout)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelCallout(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlPanelCallout(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlPanelCallout(params Control[] content) -// : this() -// { -// Content.AddRange(content); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = Css.Concatenate("callout", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanelCallout(string id, params Control[] content) -// : this(id) -// { -// Content.AddRange(content); -// } + if (Title != null) + { + html.Add(new HtmlElementTextSemanticsSpan(new HtmlText(Title)) + { + Class = "callout-title" + }); + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = Css.Concatenate("callout", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; + html.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Class = "callout-body" + }); -// if (Title != null) -// { -// html.Elements.Add(new HtmlElementTextSemanticsSpan(new HtmlText(Title)) -// { -// Class = "callout-title" -// }); -// } - -// html.Elements.Add(new HtmlElementTextContentDiv(from x in Content select x.Render(context)) -// { -// Class = "callout-body" -// }); - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs index 0eb870d2..67e4eeab 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs @@ -1,65 +1,40 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelCenter : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelCenter(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that centers its child controls within its layout. + /// + public class ControlPanelCenter : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlPanelCenter(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlPanelCenter(params Control[] content) -// : this() -// { -// Content.AddRange(content); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanelCenter(string id, params Control[] content) -// : this(id) -// { -// Content.AddRange(content); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs index f11dbc5a..c05810c0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs @@ -1,67 +1,42 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelNavbar : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelNavbar(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a navigation bar control panel that can contain multiple child controls. + /// + public class ControlPanelNavbar : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The navbar items. + public ControlPanelNavbar(string id = null, params IControl[] items) + : base(id, items) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The navbar items. -// public ControlPanelNavbar(string id, params Control[] items) -// : base(id, items) -// { -// Init(); -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementSectionNav() + { + Id = Id, + Class = Css.Concatenate("navbar", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The navbar items. -// public ControlPanelNavbar(params Control[] items) -// : base(items) -// { -// Init(); -// } + html.Add(from x in Content select x?.Render(renderContext)); -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementSectionNav() -// { -// Id = Id, -// Class = Css.Concatenate("navbar", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// html.Elements.AddRange(from x in Content select x?.Render(context)); - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs index f3461a36..68b9ad60 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelToast.cs @@ -1,14 +1,19 @@ -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelToast : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelToast(string id) -// : base(id) -// { -// } -// } -//} +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a toast notification control panel that can contain + /// multiple child controls. + /// + public class ControlPanelToast : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel. + public ControlPanelToast(string id = null, params ControlAlert[] controls) + : base(id, controls) + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs index 76e8407e..18f9559a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs @@ -1,209 +1,227 @@ -using System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a split button control that can contain multiple items. - /// - public class ControlSplitButton : Control, IControlButton - { - private readonly List _items = []; - - /// - /// Returns or sets the background color. - /// - public new PropertyColorButton BackgroundColor - { - get => (PropertyColorButton)GetPropertyObject(); - set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); - } - - /// - /// Returns or sets the size. - /// - public TypeSizeButton Size - { - get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the outline property - /// - public bool Outline { get; set; } - - /// - /// Returns or sets whether the button should take up the full width. - /// - public TypeBlockButton Block - { - get => (TypeBlockButton)GetProperty(TypeBlockButton.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets the text. - /// - public string Text { get; set; } - - /// - /// Returns or sets the value. - /// - public string Value { get; set; } - - /// - /// Returns or sets the icon. - /// - public PropertyIcon Icon { get; set; } - - /// - /// Returns or sets the activation status of the button. - /// - public TypeActive Active - { - get => (TypeActive)GetProperty(TypeActive.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Returns or sets a modal dialogue. - /// - public PropertyModal Modal { get; set; } = new PropertyModal(); - - /// - /// Returns or sets the content. - /// - public IEnumerable Items => _items; - - /// - /// Initializes a new instance of the class. - /// - /// The content of the html element. - public ControlSplitButton(string id = null, params IControlSplitButtonItem[] items) - : base(id) - { - Size = TypeSizeButton.Default; - _items.AddRange(items); - } - - /// - /// Adds one or more items to the split button. - /// - /// The items to add to the split button. - public void Add(params IControlSplitButtonItem[] items) - { - _items.AddRange(items); - } - /// - /// Adds one or more items to the split button. - /// - /// The items to add to the split button. - public void Add(IEnumerable items) - { - _items.AddRange(items); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) - { - var button = new HtmlElementFieldButton() - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", - Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), - Style = GetStyles() - }; - - if (Icon != null && Icon.HasIcon) - { - button.Add(new ControlIcon() - { - Icon = Icon, - Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin - ( - PropertySpacing.Space.None, - PropertySpacing.Space.Two, - PropertySpacing.Space.None, - PropertySpacing.Space.None - ) : new PropertySpacingMargin(PropertySpacing.Space.None), - VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); - } - - if (!string.IsNullOrWhiteSpace(Text)) - { - button.Add(new HtmlText(Text)); - } - - if (Modal == null || Modal.Type == TypeModal.None) - { - - } - else if (Modal.Type == TypeModal.Form) - { - button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - } - else if (Modal.Type == TypeModal.Brwoser) - { - button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; - } - else if (Modal.Type == TypeModal.Modal) - { - button.AddUserAttribute("data-bs-toggle", "modal"); - button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - } - - var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) - { - Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_toggle", - Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), - Style = GetStyles(), - DataToggle = "dropdown" - }; - dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); - dropdownButton.AddUserAttribute("aria-expanded", "false"); - - var dropdownElements = new HtmlElementTextContentUl - ( - Items.Select - ( - x => - x == null || x is ControlDropdownItemDivider || x is ControlLine ? - new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : - x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } - ).ToArray() - ) - { - Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" - }; - - var html = new HtmlElementTextContentDiv - ( - Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(renderContext)) : button, - dropdownButton, - dropdownElements - ) - { - Id = Id, - Class = Css.Concatenate - ( - "btn-group", - Margin.ToClass(), - (Block == TypeBlockButton.Block ? "btn-block" : "") - ), - Role = Role - }; - - return html; - } - } -} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a split button control that can contain multiple items. + /// + public class ControlSplitButton : Control, IControlButton + { + private readonly List _items = []; + + /// + /// Returns or sets the background color. + /// + public new PropertyColorButton BackgroundColor + { + get => (PropertyColorButton)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(Outline), () => value?.ToStyle(Outline)); + } + + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the outline property + /// + public bool Outline { get; set; } + + /// + /// Returns or sets whether the button should take up the full width. + /// + public TypeBlockButton Block + { + get => (TypeBlockButton)GetProperty(TypeBlockButton.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Returns or sets the value. + /// + public string Value { get; set; } + + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } + + /// + /// Returns or sets the activation status of the button. + /// + public TypeActive Active + { + get => (TypeActive)GetProperty(TypeActive.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets a modal dialogue. + /// + public PropertyModal Modal { get; set; } = new PropertyModal(); + + /// + /// Returns or sets the content. + /// + public IEnumerable Items => _items; + + /// + /// Initializes a new instance of the class. + /// + /// The content of the html element. + public ControlSplitButton(string id = null, params IControlSplitButtonItem[] items) + : base(id) + { + Size = TypeSizeButton.Default; + _items.AddRange(items); + } + + /// + /// Adds one or more items to the split button. + /// + /// The items to add to the split button. + public void Add(params IControlSplitButtonItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds one or more items to the split button. + /// + /// The items to add to the split button. + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Adds a divider to the split button. + /// + public void AddDivider() + { + _items.Add(null); + } + + /// + /// Adds a header item to the split button. + /// + /// The text of the header item. + public void AddHeader(string text) + { + _items.Add(new ControlSplitButtonItemHeader() { Text = text }); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var button = new HtmlElementFieldButton() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles() + }; + + if (Icon != null && Icon.HasIcon) + { + button.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + button.Add(new HtmlText(Text)); + } + + if (Modal == null || Modal.Type == TypeModal.None) + { + + } + else if (Modal.Type == TypeModal.Form) + { + button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + } + else if (Modal.Type == TypeModal.Brwoser) + { + button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + } + else if (Modal.Type == TypeModal.Modal) + { + button.AddUserAttribute("data-bs-toggle", "modal"); + button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); + } + + var dropdownButton = new HtmlElementFieldButton(new HtmlElementTextSemanticsSpan() { Class = "caret" }) + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_toggle", + Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), + Style = GetStyles(), + DataToggle = "dropdown" + }; + dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); + dropdownButton.AddUserAttribute("aria-expanded", "false"); + + var dropdownElements = new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } + ).ToArray() + ) + { + Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" + }; + + var html = new HtmlElementTextContentDiv + ( + Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(renderContext)) : button, + dropdownButton, + dropdownElements + ) + { + Id = Id, + Class = Css.Concatenate + ( + "btn-group", + Margin.ToClass(), + (Block == TypeBlockButton.Block ? "btn-block" : "") + ), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs index c87c0df8..cb967ae9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs @@ -1,228 +1,139 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlSplitButtonLink : ControlSplitButton -// { -// /// -// /// Returns or sets the target. -// /// -// public TypeTarget Target { get; set; } - -// /// -// /// Returns or sets the uri. -// /// -// public string Uri { get; set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlSplitButtonLink(string id) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlSplitButtonLink(string id, params IControlSplitButtonItem[] content) -// : base(id) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlSplitButtonLink(params IControlSplitButtonItem[] content) -// : base(id: null) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlSplitButtonLink(string id, IEnumerable content) -// : base(id) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlSplitButtonLink(IEnumerable content) -// : base(id: null) -// { -// Items.AddRange(content); - -// Init(); -// } - -// /// -// /// Fügt ein neues Item hinzu -// /// -// /// -// public void Add(IControlSplitButtonItem item) -// { -// Items.Add(item); -// } - -// /// -// /// Fügt ein neuen Seterator hinzu -// /// -// public void AddSeperator() -// { -// Items.Add(null); -// } - -// /// -// /// Fügt ein neuen Kopf hinzu -// /// -// /// Der Überschriftstext -// public void AddHeader(string text) -// { -// Items.Add(new ControlSplitButtonItemHeader() { Text = text }); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Size = TypeSizeButton.Default; -// Role = "button"; -// } - -// /// -// /// Fügt EintrÀge hinzu -// /// -// /// The entries. welcher hinzugefügt werden sollen -// public void Add(params IControlSplitButtonItem[] item) -// { -// Items.AddRange(item); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var button = new HtmlElementTextSemanticsA() -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), -// Style = GetStyles(), -// Target = Target, -// Href = Uri?.ToString(), -// OnClick = OnClick?.ToString() -// }; - -// if (Icon != null && Icon.HasIcon) -// { -// button.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } - -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// button.Elements.Add(new HtmlText(Text)); -// } - -// if (Modal == null || Modal.Type == TypeModal.None) -// { - -// } -// else if (Modal.Type == TypeModal.Form) -// { -// button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// button.Href = "#"; -// } -// else if (Modal.Type == TypeModal.Brwoser) -// { -// button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(context.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; -// button.Href = "#"; -// } -// else if (Modal.Type == TypeModal.Modal) -// { -// button.AddUserAttribute("data-bs-toggle", "modal"); -// button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); -// } - -// var dropdownButton = new HtmlElementTextSemanticsSpan(new HtmlElementTextSemanticsSpan() { Class = "caret" }) -// { -// Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", -// Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), -// Style = GetStyles() -// }; -// dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); -// dropdownButton.AddUserAttribute("aria-expanded", "false"); - -// var dropdownElements = new HtmlElementTextContentUl -// ( -// Items.Select -// ( -// x => -// x == null || x is ControlDropdownItemDivider || x is ControlLine ? -// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : -// x is ControlDropdownItemHeader ? -// x.Render(context) : -// new HtmlElementTextContentLi(x.Render(context)) { Class = "dropdown-item" } -// ) -// ) -// { -// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" -// }; - -// var html = new HtmlElementTextContentDiv -// ( -// Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(context)) : button, -// dropdownButton, -// dropdownElements -// ) -// { -// Class = Css.Concatenate -// ( -// "btn-group", -// Margin.ToClass(), -// (Block == TypeBlockButton.Block ? "btn-block" : "") -// ), -// Role = Role -// }; - -// return html; -// } -// } -//} +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a split button link control that can contain multiple items + /// and navigate to a specified URI. + /// + public class ControlSplitButtonLink : ControlSplitButton + { + /// + /// Returns or sets the target. + /// + public TypeTarget Target { get; set; } + + /// + /// Returns or sets the uri. + /// + public string Uri { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlSplitButtonLink(string id = null, params IControlSplitButtonItem[] items) + : base(id, items) + { + Size = TypeSizeButton.Default; + Role = "button"; + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var button = new HtmlElementTextSemanticsA() + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn", Css.Remove(GetClasses(), Margin.ToClass())), + Style = GetStyles(), + Target = Target, + Href = Uri?.ToString(), + OnClick = OnClick?.ToString() + }; + + if (Icon != null && Icon.HasIcon) + { + button.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } + + if (!string.IsNullOrWhiteSpace(Text)) + { + button.Add(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))); + } + + if (Modal == null || Modal.Type == TypeModal.None) + { + + } + else if (Modal.Type == TypeModal.Form) + { + button.OnClick = $"new webexpress.webui.modalFormCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + button.Href = "#"; + } + else if (Modal.Type == TypeModal.Brwoser) + { + button.OnClick = $"new webexpress.webui.modalPageCtrl({{ close: '{I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:form.cancel.label")}', uri: '{Modal.Uri?.ToString() ?? button.Href}', size: '{Modal.Size.ToString().ToLower()}', redirect: '{Modal.RedirectUri}'}});"; + button.Href = "#"; + } + else if (Modal.Type == TypeModal.Modal) + { + button.AddUserAttribute("data-bs-toggle", "modal"); + button.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); + } + + var dropdownButton = new HtmlElementTextSemanticsSpan(new HtmlElementTextSemanticsSpan() { Class = "caret" }) + { + Id = string.IsNullOrWhiteSpace(Id) ? "" : Id + "_btn", + Class = Css.Concatenate("btn dropdown-toggle dropdown-toggle-split", Css.Remove(GetClasses(), "btn-block", Margin.ToClass())), + Style = GetStyles() + }; + dropdownButton.AddUserAttribute("data-bs-toggle", "dropdown"); + dropdownButton.AddUserAttribute("aria-expanded", "false"); + + var dropdownElements = new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } + ).ToArray() + ) + { + Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" + }; + + var html = new HtmlElementTextContentDiv + ( + Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(renderContext)) : button, + dropdownButton, + dropdownElements + ) + { + Id = Id, + Class = Css.Concatenate + ( + "btn-group", + Margin.ToClass(), + (Block == TypeBlockButton.Block ? "btn-block" : "") + ), + Role = Role + }; + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs index 6f737420..cd0c6bcf 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs @@ -1,129 +1,165 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlToolbar : Control -// { -// /// -// /// Die horizontale Anordnung -// /// -// public virtual TypeOrientationToolBar Orientation -// { -// get => (TypeOrientationToolBar)GetProperty(TypeOrientationToolBar.Default); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Die fixierte Anordnung -// /// -// public virtual TypeFixed Fixed -// { -// get => (TypeFixed)GetProperty(TypeFixed.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Fixiert die Anordnung, wenn sich die Toolbar am oberen Rand befindet -// /// -// public virtual TypeSticky Sticky -// { -// get => (TypeSticky)GetProperty(TypeSticky.None); -// set => SetProperty(value, () => value.ToClass()); -// } - -// /// -// /// Returns or sets the content. -// /// -// public List Items { get; private set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlToolbar(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// Die Toolitems -// public ControlToolbar(string id = null, params IControlToolBarItem[] items) -// : this(id) -// { -// Add(items); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// Die Toolitems -// public ControlToolbar(params IControlToolBarItem[] items) -// : this((string)null) -// { -// Add(items); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// BackgroundColor = new PropertyColorBackground(TypeColorBackground.Warning); -// Orientation = TypeOrientationToolBar.Default; -// Padding = new PropertySpacingPadding(PropertySpacing.Space.Two, PropertySpacing.Space.None); -// } - -// /// -// /// Fügt EintrÀge hinzu -// /// -// /// The entries. welcher hinzugefügt werden sollen -// public void Add(params IControlToolBarItem[] item) -// { -// Items.AddRange(item); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementSectionNav() -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; - -// html.Elements.Add -// ( -// new HtmlElementTextContentUl -// ( -// Items.Select -// ( -// x => -// x == null || x is ControlDropdownItemDivider || x is ControlLine ? -// new HtmlElementTextContentLi() { Class = "divider", Inline = true } : -// x is ControlDropdownItemHeader ? -// x.Render(context) : -// new HtmlElementTextContentLi(x.Render(context)) { Class = "nav-item" } -// ) -// ) -// { -// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "" : "navbar-nav" -// } -// ); - -// return html; -// } -// } -//} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a toolbar control that can contain various toolbar items. + /// + public class ControlToolbar : Control + { + private List _items = []; + + /// + /// Returns the list of toolbar items. + /// + /// + /// A list of representing the items in the toolbar. + /// + public List Items => _items; + + /// + /// Returns or sets the orientation of the toolbar. + /// + public virtual TypeOrientationToolBar Orientation + { + get => (TypeOrientationToolBar)GetProperty(TypeOrientationToolBar.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the fixed position of the toolbar. + /// + public virtual TypeFixed Fixed + { + get => (TypeFixed)GetProperty(TypeFixed.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Returns or sets the sticky position of the toolbar. + /// + public virtual TypeSticky Sticky + { + get => (TypeSticky)GetProperty(TypeSticky.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// Die Toolitems + public ControlToolbar(string id = null, params IControlToolbarItem[] items) + : base(id) + { + BackgroundColor = new PropertyColorBackground(TypeColorBackground.Warning); + Orientation = TypeOrientationToolBar.Default; + Padding = new PropertySpacingPadding(PropertySpacing.Space.Two, PropertySpacing.Space.None); + + _items.AddRange(items); + } + + /// + /// Adds one or more toolbar items to the toolbar. + /// + /// The toolbar items to add. + /// + /// This method appends the specified collection of instances to the + /// current tool bar. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var tool = new ControlToolbar(); + /// var item1 = new ControlToolBarItemButton { Text = "Item 1" }; + /// var item2 = new ControlToolBarItemButton { Text = "Item 2" }; + /// tool.Add(item1, item2); + /// + /// This method accepts any item that derives from . + /// + public void Add(params IControlToolbarItem[] items) + { + _items.AddRange(items); + } /// + /// Adds one or more toolbar items to the toolbar. + /// + /// The toolbar items to add. + /// + /// This method appends the specified collection of instances to the + /// current tool bar. It ensures that the new items are concatenated with the existing ones, + /// maintaining the order of addition. + /// Example usage: + /// + /// var tool = new ControlToolbar(); + /// var item1 = new ControlToolBarItemButton { Text = "Item 1" }; + /// var item2 = new ControlToolBarItemButton { Text = "Item 2" }; + /// tool.Add(new List([ item1, item2 ])); + /// + /// This method accepts any item that derives from . + /// + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Removes a toolbar item from the toolbar. + /// + /// The toolbar item to remove. + /// + /// This method removes the specified instance from the + /// current tool bar. If the item does not exist in the tool bar, the method does nothing. + /// Example usage: + /// + /// var tool = new ControlToolbar(); + /// var item = new ControlToolBarItemButton { Text = "Item 1" }; + /// tool.Add(item); + /// tool.Remove(item); + /// + /// This method accepts any item that derives from . + /// + public void Remove(IControlToolbarItem item) + { + _items.Remove(item); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementSectionNav() + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; + + html.Add + ( + new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null || x is ControlDropdownItemDivider || x is ControlLine ? + new HtmlElementTextContentLi() { Class = "divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "nav-item" } + ).ToArray() + ) + { + Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "" : "navbar-nav" + } + ); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs index d6cfd09c..f13bd1e2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemButton.cs @@ -1,25 +1,23 @@ -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlToolBarItemButton : ControlLink, IControlToolBarItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlToolBarItemButton(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a toolbar item button control. + /// + /// + /// This class is used to create a button within a toolbar. + /// + public class ControlToolbarItemButton : ControlLink, IControlToolbarItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlToolbarItemButton(string id = null) + : base(id) + { + Classes.Add("nav-link"); -// /// -// /// Initialization -// /// -// private void Init() -// { -// Classes.Add("nav-link"); - -// //TextColor = LayoutSchema.ToolbarLink; -// } -// } -//} + //TextColor = LayoutSchema.ToolbarLink; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemDivider.cs new file mode 100644 index 00000000..4ac2e12f --- /dev/null +++ b/src/WebExpress.WebUI/WebControl/ControlToolbarItemDivider.cs @@ -0,0 +1,17 @@ +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a separator item in a toolbar. + /// + public class ControlToolbarItemDivider : ControlLine, IControlToolbarItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlToolbarItemDivider(string id = null) + : base(id) + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs b/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs deleted file mode 100644 index 1ff6b83c..00000000 --- a/src/WebExpress.WebUI/WebControl/ControlToolbarItemSeperator.cs +++ /dev/null @@ -1,15 +0,0 @@ -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlToolBarItemSeperator : ControlLine, IControlToolBarItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlToolBarItemSeperator(string id = null) -// : base(id) -// { - -// } -// } -//} diff --git a/src/WebExpress.WebUI/WebControl/IControlButton.cs b/src/WebExpress.WebUI/WebControl/IControlButton.cs index fabf4692..c2bd4e9e 100644 --- a/src/WebExpress.WebUI/WebControl/IControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/IControlButton.cs @@ -1,11 +1,14 @@ namespace WebExpress.WebUI.WebControl { + // + // Interface for a control button. + // public interface IControlButton : IControl { /// /// Returns or sets the color. der SchaltflÀche /// - PropertyColorButton BackgroundColor { get; set; } + new PropertyColorButton BackgroundColor { get; set; } /// /// Returns or sets the size. diff --git a/src/WebExpress.WebUI/WebControl/IControlFormLabel.cs b/src/WebExpress.WebUI/WebControl/IControlFormLabel.cs index c2827c2b..500cbacf 100644 --- a/src/WebExpress.WebUI/WebControl/IControlFormLabel.cs +++ b/src/WebExpress.WebUI/WebControl/IControlFormLabel.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Interface for form label controls. + /// public interface IControlFormLabel { /// diff --git a/src/WebExpress.WebUI/WebControl/IControlLink.cs b/src/WebExpress.WebUI/WebControl/IControlLink.cs index ebf9231b..e50769f8 100644 --- a/src/WebExpress.WebUI/WebControl/IControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/IControlLink.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Interface for a link control. + /// public interface IControlLink : IControl { } diff --git a/src/WebExpress.WebUI/WebControl/IControlNavigationItem.cs b/src/WebExpress.WebUI/WebControl/IControlNavigationItem.cs index 25347baf..2a83db85 100644 --- a/src/WebExpress.WebUI/WebControl/IControlNavigationItem.cs +++ b/src/WebExpress.WebUI/WebControl/IControlNavigationItem.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Interface for a navigation item control. + /// public interface IControlNavigationItem : IControl { } diff --git a/src/WebExpress.WebUI/WebControl/IControlSplitButtonItem.cs b/src/WebExpress.WebUI/WebControl/IControlSplitButtonItem.cs index 420a22e8..b585069a 100644 --- a/src/WebExpress.WebUI/WebControl/IControlSplitButtonItem.cs +++ b/src/WebExpress.WebUI/WebControl/IControlSplitButtonItem.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Interface for a split button item control. + /// public interface IControlSplitButtonItem : IControl { } diff --git a/src/WebExpress.WebUI/WebControl/IControlToolbarItem.cs b/src/WebExpress.WebUI/WebControl/IControlToolbarItem.cs index f0c16a56..cf835c14 100644 --- a/src/WebExpress.WebUI/WebControl/IControlToolbarItem.cs +++ b/src/WebExpress.WebUI/WebControl/IControlToolbarItem.cs @@ -1,6 +1,9 @@ namespace WebExpress.WebUI.WebControl { - public interface IControlToolBarItem : IControl + /// + /// Interface for a toolbar item control. + /// + public interface IControlToolbarItem : IControl { } } diff --git a/src/WebExpress.WebUI/WebControl/IProperty.cs b/src/WebExpress.WebUI/WebControl/IProperty.cs index c95fc840..b501aa7b 100644 --- a/src/WebExpress.WebUI/WebControl/IProperty.cs +++ b/src/WebExpress.WebUI/WebControl/IProperty.cs @@ -1,7 +1,7 @@ namespace WebExpress.WebUI.WebControl { /// - /// Kennzeichnet ein Element als Eigenschaft + /// Interface for defining properties that can be converted to CSS classes or styles. /// public interface IProperty { From 11f1b5b5cdba495619c6dd414ae6ce81a56bdfef Mon Sep 17 00:00:00 2001 From: ReneSchwarzer Date: Fri, 27 Dec 2024 21:12:15 +0100 Subject: [PATCH 29/59] refactoring and add tests --- .../WebControl/UnitTestControlAlert.cs | 24 +- .../UnitTestControlListItemButton.cs | 91 +++++ .../WebControl/UnitTestControlListItemLink.cs | 22 ++ .../WebControl/UnitTestControlPanel.cs | 2 +- .../WebControl/UnitTestControlPanelCallout.cs | 2 +- .../WebControl/UnitTestControlPanelCenter.cs | 2 +- .../WebControl/UnitTestControlPanelFlexbox.cs | 4 +- .../WebControl/UnitTestControlPanelFooter.cs | 2 +- .../WebControl/UnitTestControlPanelGrid.cs | 132 ++++++++ .../WebControl/UnitTestControlPanelHeader.cs | 149 ++++++++ .../WebControl/UnitTestControlPanelMain.cs | 2 +- .../WebControl/UnitTestControlPanelMedia.cs | 221 ++++++++++++ .../WebControl/UnitTestControlPanelNavbar.cs | 2 +- .../WebControl/UnitTestControlPanelSplit.cs | 2 +- .../WebControl/UnitTestControlPanelToast.cs | 2 +- .../WebControl/UnitTestControlPanelTool.cs | 2 +- .../WebControl/UnitTestControlTableColumn.cs | 107 ++++++ .../WebControl/UnitTestControlTableRow.cs | 85 +++++ .../WebControl/UnitTestControlTag.cs | 107 ++++++ .../WebControl/ControlFormItemButton.cs | 4 +- .../WebControl/ControlListItem.cs | 4 +- .../WebControl/ControlListItemButton.cs | 123 +++---- .../WebControl/ControlModal.cs | 2 +- .../WebControl/ControlPanel.cs | 2 +- .../WebControl/ControlPanelGrid.cs | 93 ++--- .../WebControl/ControlPanelHeader.cs | 130 +++---- .../WebControl/ControlPanelMedia.cs | 160 ++++----- .../WebControl/ControlTable.cs | 125 ++++--- .../WebControl/ControlTableColumn.cs | 204 +++++------ .../WebControl/ControlTableRow.cs | 173 +++++----- src/WebExpress.WebUI/WebControl/ControlTag.cs | 319 +++++++++--------- .../WebControl/ControlText.cs | 2 +- src/WebExpress.WebUI/WebControl/IProperty.cs | 8 +- .../WebControl/PropertyBorder.cs | 41 +-- .../WebControl/PropertyColor.cs | 18 +- .../WebControl/PropertyColorBackground.cs | 22 +- .../PropertyColorBackgroundAlert.cs | 15 +- .../PropertyColorBackgroundBadge.cs | 61 +++- .../WebControl/PropertyColorBackgroundList.cs | 19 +- .../WebControl/PropertyColorBorder.cs | 20 +- .../WebControl/PropertyColorButton.cs | 32 +- .../WebControl/PropertyColorCallout.cs | 23 +- .../WebControl/PropertyColorChart.cs | 25 +- .../WebControl/PropertyColorLine.cs | 20 +- .../WebControl/PropertyColorNavbar.cs | 19 +- .../WebControl/PropertyColorProgress.cs | 27 +- .../WebControl/PropertyColorText.cs | 21 +- .../WebControl/PropertyGrid.cs | 21 +- .../WebControl/PropertyIcon.cs | 34 +- .../WebControl/PropertyMaxSizeIcon.cs | 26 +- .../WebControl/PropertyModal.cs | 14 +- .../WebControl/PropertyOnChange.cs | 19 +- .../WebControl/PropertyOnClick.cs | 13 +- .../WebControl/PropertySizeIcon.cs | 32 +- .../WebControl/PropertySizeText.cs | 31 +- .../WebControl/PropertySpacing.cs | 50 +-- .../WebControl/PropertySpacingMargin.cs | 27 +- .../WebControl/PropertySpacingPadding.cs | 27 +- .../WebControl/RenderControlFormContext.cs | 2 +- .../RenderControlFormGroupContext.cs | 4 +- src/WebExpress.WebUI/WebControl/TypeActive.cs | 23 +- .../WebControl/TypeAlignFlexbox.cs | 35 +- .../WebControl/TypeAlignmentDropdownMenu.cs | 18 +- .../WebControl/TypeBlockButton.cs | 18 +- src/WebExpress.WebUI/WebControl/TypeButton.cs | 25 +- src/WebExpress.WebUI/WebControl/TypeChart.cs | 34 +- src/WebExpress.WebUI/WebControl/TypeColor.cs | 62 +++- .../WebControl/TypeColorBackground.cs | 54 ++- .../WebControl/TypeColorBackgroundAlert.cs | 55 ++- .../WebControl/TypeColorBackgroundBadge.cs | 48 +++ .../WebControl/TypeColorBackgroundList.cs | 49 +++ .../WebControl/TypeColorBorder.cs | 55 ++- .../WebControl/TypeColorButton.cs | 37 +- .../WebControl/TypeColorCallout.cs | 47 ++- .../WebControl/TypeColorChart.cs | 47 ++- .../WebControl/TypeColorLine.cs | 46 ++- .../WebControl/TypeColorNavbar.cs | 55 ++- .../WebControl/TypeColorProgress.cs | 50 ++- .../WebControl/TypeColorText.cs | 54 ++- src/WebExpress.WebUI/WebControl/TypeDevice.cs | 16 +- .../WebControl/TypeDirection.cs | 30 +- .../WebControl/TypeDismissibleAlert.cs | 19 +- .../WebControl/TypeExpandTree.cs | 23 +- src/WebExpress.WebUI/WebControl/TypeFade.cs | 27 +- .../WebControl/TypeFillChart.cs | 27 +- src/WebExpress.WebUI/WebControl/TypeFixed.cs | 23 +- .../WebControl/TypeFormatProgress.cs | 26 +- .../WebControl/TypeFormatText.cs | 97 ++++-- src/WebExpress.WebUI/WebControl/TypeHeight.cs | 34 +- .../WebControl/TypeHorizontalAlignment.cs | 22 +- .../WebControl/TypeHorizontalAlignmentTab.cs | 26 +- src/WebExpress.WebUI/WebControl/TypeIcon.cs | 11 +- .../WebControl/TypeJustifiedFlexbox.cs | 35 +- .../WebControl/TypeJustifiedTab.cs | 19 +- .../WebControl/TypeLayoutFlexbox.cs | 23 +- .../WebControl/TypeLayoutForm.cs | 9 +- .../WebControl/TypeLayoutFormItem.cs | 13 +- .../WebControl/TypeLayoutList.cs | 31 +- .../WebControl/TypeLayoutTab.cs | 26 +- .../WebControl/TypeLayoutTree.cs | 33 +- .../WebControl/TypeLayoutTreeItem.cs | 39 ++- src/WebExpress.WebUI/WebControl/TypeModal.cs | 17 +- .../WebControl/TypeModalSize.cs | 22 ++ .../WebControl/TypeOnChange.cs | 20 +- .../WebControl/TypeOrientationSplit.cs | 45 ++- .../WebControl/TypeOrientationTab.cs | 23 +- .../WebControl/TypeOrientationToolBar.cs | 23 +- .../WebControl/TypePanelContainer.cs | 20 +- .../WebControl/TypePanelGridRow.cs | 22 +- .../WebControl/TypePillBadge.cs | 19 +- .../WebControl/TypePointChart.cs | 31 +- .../WebControl/TypeSizeButton.cs | 22 +- .../WebControl/TypeSizePagination.cs | 22 +- .../WebControl/TypeSizeProgress.cs | 36 +- .../WebControl/TypeSizeText.cs | 36 +- .../WebControl/TypeSizeUnit.cs | 17 +- src/WebExpress.WebUI/WebControl/TypeSticky.cs | 19 +- .../WebControl/TypeTextDecoration.cs | 19 +- .../WebControl/TypeToggleDropdown.cs | 19 +- .../WebControl/TypeVerticalAlignment.cs | 42 ++- src/WebExpress.WebUI/WebControl/TypeWidth.cs | 30 +- src/WebExpress.WebUI/WebControl/TypeWrap.cs | 27 +- .../WebControl/TypesEditTextFormat.cs | 13 +- .../WebControl/TypesInputValidity.cs | 18 + .../WebControl/TypesLayoutTableRow.cs | 38 +++ .../WebControl/ValidationResult.cs | 57 ++-- 126 files changed, 3748 insertions(+), 1302 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs index 3cf57eb3..aa8c8566 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs @@ -1,6 +1,5 @@ using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; -using Xunit.Abstractions; namespace WebExpress.WebUI.Test.WebControl { @@ -8,29 +7,8 @@ namespace WebExpress.WebUI.Test.WebControl /// Tests the alert control. /// [Collection("NonParallelTests")] - public class UnitTestControlAlert : IClassFixture + public class UnitTestControlAlert { - /// - /// Returns the log. - /// - protected ITestOutputHelper Output { get; private set; } - - /// - /// Returns the test context. - /// - protected UnitTestControlFixture Fixture { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The log. - /// The test context. - public UnitTestControlAlert(UnitTestControlFixture fixture, ITestOutputHelper output) - { - Fixture = fixture; - Output = output; - } - /// /// Tests the id property of the alert control. /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs new file mode 100644 index 00000000..cf969bfc --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs @@ -0,0 +1,91 @@ +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the list item button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlListItemButton + { + /// + /// Tests the id property of the list item button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemButton(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the Active property of the list item button control. + /// + [Theory] + [InlineData(TypeActive.None, @"")] + [InlineData(TypeActive.Active, @"")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemButton(null) + { + Active = active + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the list item button control. + /// + [Fact] + public void Add() + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control1 = new ControlListItemButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlListItemButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlListItemButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlListItemButton(null); + var control5 = new ControlListItemButton(null); + var control6 = new ControlListItemButton(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + + var html1 = control1.Render(context); + var html2 = control2.Render(context); + var html3 = control3.Render(context); + var html4 = control4.Render(context); + var html5 = control5.Render(context); + var html6 = control6.Render(context); + + AssertExtensions.EqualWithPlaceholders(@"", html1); + AssertExtensions.EqualWithPlaceholders(@"", html2); + AssertExtensions.EqualWithPlaceholders(@"", html3); + AssertExtensions.EqualWithPlaceholders(@"", html4); + AssertExtensions.EqualWithPlaceholders(@"", html5); + AssertExtensions.EqualWithPlaceholders(@"", html6); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs index 1908f1f1..da324861 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs @@ -171,6 +171,28 @@ public void Icon(TypeIcon icon, string expected) AssertExtensions.EqualWithPlaceholders(expected, html); } + /// + /// Tests the Active property of the list item link control. + /// + [Theory] + [InlineData(TypeActive.None, @"")] + [InlineData(TypeActive.Active, @"")] + public void Active(TypeActive active, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlListItemLink(null) + { + Active = active + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + /// /// Tests the add function of the list item link control. /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs index 753f83fe..68c62325 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -107,7 +107,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the panel control. + /// Tests the add function of the panel control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs index d34051bc..1d810832 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs @@ -79,7 +79,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the panel callout control. + /// Tests the add function of the panel callout control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs index 081aa352..27d6e468 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs @@ -107,7 +107,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the center panel control. + /// Tests the add function of the center panel control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs index 9ee7e3e4..bc483ceb 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs @@ -176,13 +176,13 @@ public void Wrap(TypeWrap wrap, string expected) } /// - /// Tests the add child function of the panel flexbox control. + /// Tests the add function of the panel flexbox control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                      ")] [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                      ")] - public void AddChildren(Type child, string expected) + public void Add(Type child, string expected) { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs index 34a0a88d..30c37425 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs @@ -79,7 +79,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the panel footer control. + /// Tests the add function of the panel footer control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs new file mode 100644 index 00000000..3f0b3d70 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs @@ -0,0 +1,132 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the grid control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelGrid + { + /// + /// Tests the id property of the grid control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelGrid(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the grid control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelGrid() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the grid control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelGrid() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the grid control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelGrid() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the grid control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelGrid(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs new file mode 100644 index 00000000..9f9ae334 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs @@ -0,0 +1,149 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the panel header control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelHeader + { + /// + /// Tests the id property of the panel header control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelHeader(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the panel header control. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelHeader() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the panel header control. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelHeader() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fixed property of the panel header control. + /// + [Theory] + [InlineData(TypeFixed.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeFixed.Top, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeFixed.Bottom, @"
                                                                                                                                                                                                                                                                                      ")] + public void Fixed(TypeFixed fixedValue, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelHeader() + { + Fixed = fixedValue + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the sticky property of the panel header control. + /// + [Theory] + [InlineData(TypeSticky.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeSticky.Top, @"
                                                                                                                                                                                                                                                                                      ")] + public void Sticky(TypeSticky sticky, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelHeader() + { + Sticky = sticky, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the panel header control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelHeader(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs index 42467274..a86daa4a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs @@ -79,7 +79,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the panel main control. + /// Tests the add function of the panel main control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs new file mode 100644 index 00000000..5550a74a --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs @@ -0,0 +1,221 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the media control panel. + /// + [Collection("NonParallelTests")] + public class UnitTestControlPanelMedia + { + /// + /// Tests the id property of the media control panel. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the media control panel. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the direction property of the media control panel. + /// + [Theory] + [InlineData(TypeDirection.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Vertical, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.VerticalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.Horizontal, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeDirection.HorizontalReverse, @"
                                                                                                                                                                                                                                                                                      ")] + public void Direction(TypeDirection direction, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + Direction = direction, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the fluid property of the media control panel. + /// + [Theory] + [InlineData(TypePanelContainer.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypePanelContainer.Fluid, @"
                                                                                                                                                                                                                                                                                      ")] + public void Fluid(TypePanelContainer fluid, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + Fluid = fluid, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title property of the media control panel. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("Title", @"

                                                                                                                                                                                                                                                                                      Title

                                                                                                                                                                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"

                                                                                                                                                                                                                                                                                      WebExpress.WebUI

                                                                                                                                                                                                                                                                                      ")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + Title = title + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the image property of the media control panel. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("image.jpg", @"
                                                                                                                                                                                                                                                                                      ")] + public void Image(string image, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + Image = image + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the image width property of the media control panel. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(100u, @"
                                                                                                                                                                                                                                                                                      ")] + public void ImageWidth(uint? imageWidth, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + ImageWidth = imageWidth + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the image height property of the media control panel. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(100u, @"
                                                                                                                                                                                                                                                                                      ")] + public void ImageHeight(uint? imageHeight, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlPanelMedia() + { + ImageHeight = imageHeight + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the media control panel. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var control = new ControlPanelMedia(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs index 54ad24b0..a07a8de0 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs @@ -107,7 +107,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the navbar control. + /// Tests the add function of the navbar control. /// [Theory] [InlineData(typeof(ControlText), @"")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs index 68825c9f..89ca29d4 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs @@ -82,7 +82,7 @@ public void SplitterColor(TypeColorBackground splitterColor, string expected) } /// - /// Tests the add child function of the panel split control. + /// Tests the add function of the panel split control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs index 2a1c16b9..de7be8ab 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs @@ -107,7 +107,7 @@ public void Fluid(TypePanelContainer fluid, string expected) } /// - /// Tests the add child function of the toast control. + /// Tests the add function of the toast control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs index 9d524328..682ec4d5 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs @@ -103,7 +103,7 @@ public void Tools(string text, string expected) } /// - /// Tests the add child function of the tool panel control. + /// Tests the add function of the tool panel control. /// [Theory] [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs new file mode 100644 index 00000000..480d5149 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs @@ -0,0 +1,107 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the table column control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTableColumn + { + /// + /// Tests the id property of the table column control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableColumn(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the table column control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                                                                      abc
                                                                                                                                                                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                                                                                                                                                                      WebExpress.WebUI
                                                                                                                                                                                                                                                                                      ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableColumn() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the layout property of the table column control. + /// + [Theory] + [InlineData(TypesLayoutTableRow.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + public void Layout(TypesLayoutTableRow layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableColumn() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the table column control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeIcon.Star, @"
                                                                                                                                                                                                                                                                                      ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableColumn() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs new file mode 100644 index 00000000..5eb122b3 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs @@ -0,0 +1,85 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the table row control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTableRow + { + /// + /// Tests the id property of the table row control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableRow(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the layout property of the table row control. + /// + [Theory] + [InlineData(TypesLayoutTableRow.Default, @"")] + [InlineData(TypesLayoutTableRow.Primary, @"")] + [InlineData(TypesLayoutTableRow.Secondary, @"")] + [InlineData(TypesLayoutTableRow.Info, @"")] + [InlineData(TypesLayoutTableRow.Success, @"")] + [InlineData(TypesLayoutTableRow.Warning, @"")] + [InlineData(TypesLayoutTableRow.Danger, @"")] + [InlineData(TypesLayoutTableRow.Light, @"")] + [InlineData(TypesLayoutTableRow.Dark, @"")] + public void Layout(TypesLayoutTableRow layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTableRow() + { + Layout = layout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the table row control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"")] + [InlineData(typeof(ControlImage), @"")] + public void Add(Type cell, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(cell, [null]) as IControl; + var control = new ControlTableRow(); + + // test execution + control.Add(childInstance); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs new file mode 100644 index 00000000..57f78fc8 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs @@ -0,0 +1,107 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the tag control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTag + { + /// + /// Tests the id property of the tag control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTag(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the tag control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"abc")] + [InlineData("webexpress.webui:plugin.name", @"WebExpress.WebUI")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTag() + { + Text = text + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the pill property of the tag control. + /// + [Theory] + [InlineData(false, @"")] + [InlineData(true, @"")] + public void Pill(bool pill, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTag() + { + Pill = pill + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the layout property of the tag control. + /// + [Theory] + [InlineData(TypeColorBackgroundBadge.Default, @"")] + [InlineData(TypeColorBackgroundBadge.Primary, @"")] + [InlineData(TypeColorBackgroundBadge.Secondary, @"")] + [InlineData(TypeColorBackgroundBadge.Info, @"")] + [InlineData(TypeColorBackgroundBadge.Success, @"")] + [InlineData(TypeColorBackgroundBadge.Warning, @"")] + [InlineData(TypeColorBackgroundBadge.Danger, @"")] + [InlineData(TypeColorBackgroundBadge.Light, @"")] + [InlineData(TypeColorBackgroundBadge.Dark, @"")] + public void Layout(TypeColorBackgroundBadge layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTag() + { + Layout = new PropertyColorBackgroundBadge(layout) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs index 65377d37..1142313e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs @@ -130,7 +130,7 @@ public virtual void Add(params IControl[] controls) /// /// This method accepts any control that implements the interface. /// - public void Add(IEnumerable controls) + public void Add(IEnumerable controls) { _content.AddRange(controls); } @@ -143,7 +143,7 @@ public void Add(IEnumerable controls) /// This method allows removing a specific control from the collection of /// the control panel. /// - public void Remove(Control control) + public void Remove(IControl control) { _content.Remove(control); } diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index 74da07d9..9598bd5d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -30,7 +30,7 @@ public TypeActive Active /// Initializes a new instance of the class. ///
                                                                                                                                                                                                                                                                                      /// The id of the control. - public ControlListItem(string id = null, params Control[] content) + public ControlListItem(string id = null, params IControl[] content) : base(id) { _content.AddRange(content); @@ -88,7 +88,7 @@ public virtual void Add(IEnumerable controls) /// This method allows removing a specific control from the collection of /// the list item. /// - public virtual void Remove(Control control) + public virtual void Remove(IControl control) { _content.Remove(control); } diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs index 97c3da0c..be509297 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs @@ -1,85 +1,42 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlListItemButton : ControlListItem -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlListItemButton(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a button control within a list item. + /// + /// + /// This control is used to create a button element within a list item, + /// allowing for interactive list items. + /// + public class ControlListItemButton : ControlListItem + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlListItemButton(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlListItemButton(string id, params Control[] content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlListItemButton(params Control[] content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlListItemButton(string id, List content) -// : base(id, content) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlListItemButton(List content) -// : base(content) -// { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementFieldButton(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = Css.Concatenate("list-group-item-action", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementFieldButton(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = Css.Concatenate("list-group-item-action", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index 60f38e15..9e90ceab 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -107,7 +107,7 @@ public virtual void Add(IEnumerable controls) /// This method allows removing a specific control from the collection of /// the modal. /// - public virtual void Remove(Control control) + public virtual void Remove(IControl control) { _content.Remove(control); } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 5de2e9b5..755feae3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -102,7 +102,7 @@ public virtual void Add(IEnumerable controls) /// This method allows removing a specific control from the collection of /// the control panel. /// - public virtual void Remove(Control control) + public virtual void Remove(IControl control) { _content.Remove(control); } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs index 4ba51fc3..6078db75 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs @@ -1,50 +1,51 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Grid of 12 cells per row. -// /// -// public class ControlPanelGrid : ControlPanel -// { -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelGrid(string id = null) -// : base(id) -// { -// Init(); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a grid control panel with 12 cells per row. + /// + /// + /// This class is a specialized version of the that arranges + /// its child controls in a grid layout with 12 cells per row. + /// + public class ControlPanelGrid : ControlPanel + { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlPanelGrid(string id = null) + : base(id) + { + } -// /// -// /// Initialization -// /// -// private void Init() -// { + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; -// } + html.Add(new HtmlElementTextContentDiv + ( + Content.Select(x => x.Render(renderContext)).ToArray() + ) + { + Class = "row" + }); -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; - -// html.Elements.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(context))) { Class = "row" }); - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs index e50df866..8f83b8ec 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs @@ -1,81 +1,57 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelHeader : ControlPanel -// { -// /// -// /// Returns or sets the fixed arrangement. -// /// -// public virtual TypeFixed Fixed -// { -// get => (TypeFixed)GetProperty(TypeFixed.None); -// set => SetProperty(value, () => value.ToClass()); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a header control panel that can contain multiple child controls and manage + /// their layout and rendering. + /// + public class ControlPanelHeader : ControlPanel + { + /// + /// Returns or sets the fixed arrangement. + /// + public virtual TypeFixed Fixed + { + get => (TypeFixed)GetProperty(TypeFixed.None); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets the pinned arrangement when the toolbar is at the top. -// /// -// public virtual TypeSticky Sticky -// { -// get => (TypeSticky)GetProperty(TypeSticky.None); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the pinned arrangement when the toolbar is at the top. + /// + public virtual TypeSticky Sticky + { + get => (TypeSticky)GetProperty(TypeSticky.None); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelHeader(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlPanelHeader(string id = null, params IControl[] content) + : base(id, content) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlPanelHeader(params Control[] content) -// : this() -// { -// Content.AddRange(content); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlPanelHeader(string id, params Control[] content) -// : this(id) -// { -// Content.AddRange(content); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementSectionHeader(from x in Content select x.Render(context)) -// { -// Id = Id, -// Class = GetClasses(), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementSectionHeader(Content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs index f43356e3..b6590c45 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs @@ -1,98 +1,88 @@ -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlPanelMedia : ControlPanel -// { -// /// -// /// Returns or sets the title. -// /// -// public Control Title { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a media control panel that can display an image and a title. + /// + public class ControlPanelMedia : ControlPanel + { + /// + /// Returns or sets the title. + /// + public string Title { get; set; } -// /// -// /// Returns or sets the uri to the image. -// /// -// public string Image { get; set; } + /// + /// Returns or sets the uri to the image. + /// + public string Image { get; set; } -// /// -// /// Returns or sets the width of the image in pixel. -// /// -// public int ImageWidth { get; set; } = -1; + /// + /// Returns or sets the width of the image in pixel. + /// + public uint? ImageWidth { get; set; } -// /// -// /// Returns or sets the height of the image in pixel. -// /// -// public int ImageHeight { get; set; } = -1; + /// + /// Returns or sets the height of the image in pixel. + /// + public uint? ImageHeight { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlPanelMedia(string id = null) -// : base(id) -// { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The headline. + public ControlPanelMedia(string id = null) + : base(id) + { + } -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var img = new HtmlElementMultimediaImg() + { + Src = Image?.ToString(), + Class = "me-3 mt-3 " // rounded-circle + }; -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The headline. -// public ControlPanelMedia(string id, string title) -// : this(id) -// { -// Title = new ControlText(string.IsNullOrWhiteSpace(id) ? null : id + "_header") -// { -// Text = title -// }; -// } + if (ImageWidth.HasValue) + { + img.Width = (int)ImageWidth; + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var img = new HtmlElementMultimediaImg() -// { -// Src = Image?.ToString(), -// Class = "me-3 mt-3 " // rounded-circle -// }; + if (ImageHeight.HasValue) + { + img.Height = (int)ImageHeight; + } -// if (ImageWidth > -1) -// { -// img.Width = ImageWidth; -// } + var heading = !string.IsNullOrWhiteSpace(Title) + ? new HtmlElementSectionH4(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Title))) + : null; -// if (ImageHeight > -1) -// { -// img.Height = ImageHeight; -// } + var body = new HtmlElementTextContentDiv(heading) + { + Class = "media-body" + }; -// var heading = new HtmlElementSectionH4(Title?.Render(context)) -// { -// }; + body.Add(Content.Select(x => x.Render(renderContext))); -// var body = new HtmlElementTextContentDiv(Title != null ? heading : null) -// { -// Class = "media-body" -// }; + var html = new HtmlElementTextContentDiv(img, body) + { + Id = Id, + Class = Css.Concatenate("media", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// body.Elements.AddRange(from x in Content select x.Render(context)); - -// var html = new HtmlElementTextContentDiv(img, body) -// { -// Id = Id, -// Class = Css.Concatenate("media", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlTable.cs b/src/WebExpress.WebUI/WebControl/ControlTable.cs index d4ae73e1..1318744b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTable.cs @@ -5,62 +5,57 @@ //namespace WebExpress.WebUI.WebControl //{ +// / +// / Represents a table control. +// / // public class ControlTable : Control // { -// /// -// /// Returns or sets the layout. der Spaltenüberschrift -// /// +// / +// / Returns or sets the layout. der Spaltenüberschrift +// / // public TypesLayoutTableRow ColumnLayout { get; set; } -// /// -// /// Returns or sets the columns. -// /// +// / +// / Returns or sets the columns. +// / // public List Columns { get; private set; } -// /// -// /// Returns or sets the rows. -// /// +// / +// / Returns or sets the rows. +// / // public List Rows { get; private set; } -// /// -// /// Returns or sets the responsive property. -// /// +// / +// / Returns or sets the responsive property. +// / // public bool Responsive { get; set; } -// /// -// /// Returns or sets the striped property. -// /// +// / +// / Returns or sets the striped property. +// / // public bool Striped { get; set; } -// /// -// /// Returns or sets the table to be rotated. -// /// +// / +// / Returns or sets the table to be rotated. +// / // public bool Reflow { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. +// / +// / Initializes a new instance of the class. +// / +// / The id of the control. // public ControlTable(string id = null) // : base(id) // { -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { // Striped = true; // Columns = new List(); // Rows = new List(); // } -// /// -// /// Adds a column. -// /// -// /// The header of the column. +// / +// / Adds a column. +// / +// / The header of the column. // public virtual void AddColumn(string name) // { // Columns.Add(new ControlTableColumn(null) @@ -69,11 +64,11 @@ // }); // } -// /// -// /// Adds a column. -// /// -// /// The header of the column. -// /// The icon of the column. +// / +// / Adds a column. +// / +// / The header of the column. +// / The icon of the column. // public virtual void AddColumn(string name, PropertyIcon icon) // { // Columns.Add(new ControlTableColumn(null) @@ -83,12 +78,12 @@ // }); // } -// /// -// /// Adds a column. -// /// -// /// The header of the column. -// /// The icon of the column. -// /// The layout of the column. +// / +// / Adds a column. +// / +// / The header of the column. +// / The icon of the column. +// / The layout of the column. // public virtual void AddColumn(string name, PropertyIcon icon, TypesLayoutTableRow layout) // { // Columns.Add(new ControlTableColumn(null) @@ -99,10 +94,10 @@ // }); // } -// /// -// /// Adds a row. -// /// -// /// The cells of the row. +// / +// / Adds a row. +// / +// / The cells of the row. // public void AddRow(params Control[] cells) // { // var r = new ControlTableRow(null); @@ -111,11 +106,11 @@ // Rows.Add(r); // } -// /// -// /// Adds a row. -// /// -// /// The cells of the row. -// /// The css class. +// / +// / Adds a row. +// / +// / The cells of the row. +// / The css class. // public void AddRow(Control[] cells, string cssClass = null) // { // var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }) }; @@ -124,12 +119,12 @@ // Rows.Add(r); // } -// /// -// /// Adds a row. -// /// -// /// The cells of the row. -// /// The layout. -// /// The css class. +// / +// / Adds a row. +// / +// / The cells of the row. +// / The layout. +// / The css class. // public void AddRow(Control[] cells, TypesLayoutTableRow layout, string cssClass = null) // { // var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }), Layout = layout }; @@ -138,11 +133,11 @@ // Rows.Add(r); // } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. +// / +// / Convert to html. +// / +// / The context in which the control is rendered. +// / The control as html. // public override IHtmlNode Render(IRenderContext context) // { // Columns.ForEach(x => x.Layout = ColumnLayout); diff --git a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs index b188c1a7..b90ab3a9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs @@ -1,113 +1,113 @@ -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Zeile der Tabelle -// /// -// public class ControlTableColumn : Control -// { -// /// -// /// Returns or sets the layout. -// /// -// public TypesLayoutTableRow Layout { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a table column control. + /// + public class ControlTableColumn : Control + { + /// + /// Returns or sets the layout. + /// + public TypesLayoutTableRow Layout { get; set; } -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTableColumn(string id) -// : base(id) -// { + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlTableColumn(string id = null) + : base(id) + { -// } + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var classes = Classes.ToList(); + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var classes = Classes.ToList(); -// switch (Layout) -// { -// case TypesLayoutTableRow.Primary: -// classes.Add("table-primary"); -// break; -// case TypesLayoutTableRow.Secondary: -// classes.Add("table-secondary"); -// break; -// case TypesLayoutTableRow.Success: -// classes.Add("table-success"); -// break; -// case TypesLayoutTableRow.Info: -// classes.Add("table-info"); -// break; -// case TypesLayoutTableRow.Warning: -// classes.Add("table-warning"); -// break; -// case TypesLayoutTableRow.Danger: -// classes.Add("table-danger"); -// break; -// case TypesLayoutTableRow.Light: -// classes.Add("table-light"); -// break; -// case TypesLayoutTableRow.Dark: -// classes.Add("table-dark"); -// break; -// } + switch (Layout) + { + case TypesLayoutTableRow.Primary: + classes.Add("table-primary"); + break; + case TypesLayoutTableRow.Secondary: + classes.Add("table-secondary"); + break; + case TypesLayoutTableRow.Success: + classes.Add("table-success"); + break; + case TypesLayoutTableRow.Info: + classes.Add("table-info"); + break; + case TypesLayoutTableRow.Warning: + classes.Add("table-warning"); + break; + case TypesLayoutTableRow.Danger: + classes.Add("table-danger"); + break; + case TypesLayoutTableRow.Light: + classes.Add("table-light"); + break; + case TypesLayoutTableRow.Dark: + classes.Add("table-dark"); + break; + } -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; -// if (Icon != null && Icon.HasIcon) -// { -// html.Elements.Add(new ControlIcon() -// { -// Icon = Icon, -// Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin -// ( -// PropertySpacing.Space.None, -// PropertySpacing.Space.Two, -// PropertySpacing.Space.None, -// PropertySpacing.Space.None -// ) : new PropertySpacingMargin(PropertySpacing.Space.None), -// VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default -// }.Render(context)); -// } + if (Icon != null && Icon.HasIcon) + { + html.Add(new ControlIcon() + { + Icon = Icon, + Margin = !string.IsNullOrWhiteSpace(Text) ? new PropertySpacingMargin + ( + PropertySpacing.Space.None, + PropertySpacing.Space.Two, + PropertySpacing.Space.None, + PropertySpacing.Space.None + ) : new PropertySpacingMargin(PropertySpacing.Space.None), + VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default + }.Render(renderContext)); + } -// if (!string.IsNullOrWhiteSpace(Text)) -// { -// html.Elements.Add(new HtmlText(I18N.Translate(context.Culture, Text))); -// } + if (!string.IsNullOrWhiteSpace(Text)) + { + html.Add(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))); + } -// return new HtmlElementTableTh(html) -// { -// Id = Id, -// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; -// } -// } -//} + return new HtmlElementTableTh(html) + { + Id = Id, + Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs index a02b49d9..47163503 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs @@ -1,77 +1,96 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Zeile der Tabelle -// /// -// public class ControlTableRow : Control -// { -// /// -// /// Returns or sets the layout. -// /// -// public TypesLayoutTableRow Layout { get; set; } - -// /// -// /// Returns or set the cells. -// /// -// public List Cells { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTableRow(string id = null) -// : base(id) -// { -// Cells = new List(); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// switch (Layout) -// { -// case TypesLayoutTableRow.Primary: -// Classes.Add("table-primary"); -// break; -// case TypesLayoutTableRow.Secondary: -// Classes.Add("table-secondary"); -// break; -// case TypesLayoutTableRow.Success: -// Classes.Add("table-success"); -// break; -// case TypesLayoutTableRow.Info: -// Classes.Add("table-info"); -// break; -// case TypesLayoutTableRow.Warning: -// Classes.Add("table-warning"); -// break; -// case TypesLayoutTableRow.Danger: -// Classes.Add("table-danger"); -// break; -// case TypesLayoutTableRow.Light: -// Classes.Add("table-light"); -// break; -// case TypesLayoutTableRow.Dark: -// Classes.Add("table-dark"); -// break; -// } - -// return new HtmlElementTableTr(from c in Cells select new HtmlElementTableTd(c.Render(context))) -// { -// Id = Id, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; -// } -// } -//} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a table row control. + /// + public class ControlTableRow : Control + { + private readonly List _cells = []; + + /// + /// Returns or set the cells. + /// + public IEnumerable Cells { get; private set; } + + /// + /// Returns or sets the layout. + /// + public TypesLayoutTableRow Layout { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The cells to be added to the row. + public ControlTableRow(string id = null, params IControl[] cells) + : base(id) + { + _cells.AddRange(cells); + } /// + /// Adds the specified cells to the row. + /// + /// The cells to be added to the row. + public void Add(params IControl[] cells) + { + _cells.AddRange(cells); + } + + /// + /// Removes the specified cell from the row. + /// + /// The cell to be removed from the row. + public void Remove(IControl cell) + { + _cells.Remove(cell); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + switch (Layout) + { + case TypesLayoutTableRow.Primary: + Classes.Add("table-primary"); + break; + case TypesLayoutTableRow.Secondary: + Classes.Add("table-secondary"); + break; + case TypesLayoutTableRow.Success: + Classes.Add("table-success"); + break; + case TypesLayoutTableRow.Info: + Classes.Add("table-info"); + break; + case TypesLayoutTableRow.Warning: + Classes.Add("table-warning"); + break; + case TypesLayoutTableRow.Danger: + Classes.Add("table-danger"); + break; + case TypesLayoutTableRow.Light: + Classes.Add("table-light"); + break; + case TypesLayoutTableRow.Dark: + Classes.Add("table-dark"); + break; + } + + return new HtmlElementTableTr(_cells.Select(c => new HtmlElementTableTd(c.Render(renderContext))).ToArray()) + { + Id = Id, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlTag.cs b/src/WebExpress.WebUI/WebControl/ControlTag.cs index 502b4a31..aa12eade 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTag.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTag.cs @@ -1,165 +1,154 @@ -//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlTag : Control -// { -// /// -// /// Returns or sets the layout. -// /// -// public TypeColorBackgroundBadge Layout { get; set; } - -// /// -// /// Return or specifies whether rounded corners should be used. -// /// -// public bool Pill { get; set; } - -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } - -// /// -// /// Returns or sets the content. -// /// -// protected List Items { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlTag(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTag(string id, params Control[] content) -// : this(id) -// { -// Items.AddRange(content); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The content of the html element. -// public ControlTag(string id, IEnumerable content) -// : this(id) -// { -// Items.AddRange(content); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Pill = true; -// Items = new List(); -// } - -// /// -// /// Fügt ein neues Item hinzu -// /// -// /// -// public void Add(Control item) -// { -// Items.Add(item); -// } - -// /// -// /// Fügt ein neuen Seterator hinzu -// /// -// public void AddSeperator() -// { -// Items.Add(null); -// } - -// /// -// /// Fügt ein neuen Kopf hinzu -// /// -// /// Der Überschriftstext -// public void AddHeader(string text) -// { -// Items.Add(new ControlDropdownItemHeader() { Text = text }); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { - -// if (Pill) -// { -// Classes.Add("badge-pill"); -// } - -// if (Items.Count == 0) -// { -// return new HtmlElementTextSemanticsSpan(new HtmlText(Text)) -// { -// Class = Css.Concatenate("badge", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } - -// Classes.Add("btn"); - -// var html = new HtmlElementTextSemanticsSpan() -// { -// Id = Id, -// Class = "dropdown" -// }; - -// var tag = new HtmlElementTextSemanticsSpan -// ( -// new HtmlText(Text), new HtmlElementTextSemanticsSpan() -// { -// Class = "fas fa-caret-down" -// } -// ) -// { -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// DataToggle = "dropdown" -// }; - -// html.Elements.Add(tag); -// html.Elements.Add -// ( -// new HtmlElementTextContentUl -// ( -// Items.Select -// ( -// x => -// x == null ? -// new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : -// x is ControlDropdownItemHeader ? -// x.Render(context) : -// new HtmlElementTextContentLi(x.Render(context).AddClass("dropdown-item")) { } -// ) -// ) -// { -// Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" -// } -// ); - -// return html; -// } -// } -//} +using System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control tag. + /// + public class ControlTag : Control + { + private readonly List _items = []; + + /// + /// Returns the collection of items contained in the control. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the layout. + /// + public PropertyColorBackgroundBadge Layout + { + get => (PropertyColorBackgroundBadge)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } + + /// + /// Return or specifies whether rounded corners should be used. + /// + public bool Pill { get; set; } + + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The content of the html element. + public ControlTag(string id = null, params IControl[] content) + : base(id) + { + Pill = true; + _items.AddRange(content); + } + + /// + /// Adds the specified items to the control. + /// + /// The items to add. + public void Add(params IControl[] items) + { + _items.AddRange(items); + } + /// + /// Adds a divider to the control. + /// + public void AddDivider() + { + _items.AddRange(null); + } + + /// + /// Removes the specified item from the control. + /// + /// The item to remove. + public void Remove(IControl item) + { + _items.Remove(item); + } + + /// + /// Adds a header to the control. + /// + /// The header text. + public void AddHeader(string text) + { + _items.AddRange(new ControlDropdownItemHeader() { Text = text }); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + if (Pill) + { + Classes.Add("badge-pill"); + } + + if (_items.Count == 0) + { + return new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))) + { + Id = Id, + Class = Css.Concatenate("badge", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + + Classes.Add("btn"); + + var html = new HtmlElementTextSemanticsSpan() + { + Id = Id, + Class = "dropdown" + }; + + var tag = new HtmlElementTextSemanticsSpan + ( + new HtmlText(Text), new HtmlElementTextSemanticsSpan() + { + Class = "fas fa-caret-down" + } + ) + { + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + DataToggle = "dropdown" + }; + + html.Add(tag); + html.Add + ( + new HtmlElementTextContentUl + ( + Items.Select + ( + x => + x == null ? + new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : + x is ControlDropdownItemHeader ? + x.Render(renderContext) : + new HtmlElementTextContentLi(x.Render(renderContext).AddClass("dropdown-item")) { } + ).ToArray() + ) + { + Class = HorizontalAlignment == TypeHorizontalAlignment.Right ? "dropdown-menu dropdown-menu-right" : "dropdown-menu" + } + ); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlText.cs b/src/WebExpress.WebUI/WebControl/ControlText.cs index 1b44f573..436478ed 100644 --- a/src/WebExpress.WebUI/WebControl/ControlText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlText.cs @@ -63,7 +63,7 @@ public ControlText(string id = null) public override IHtmlNode Render(IRenderControlContext renderContext) { var text = I18N.Translate(renderContext?.Request.Culture, Text); - HtmlElement html; + var html = default(HtmlElement); switch (Format) { diff --git a/src/WebExpress.WebUI/WebControl/IProperty.cs b/src/WebExpress.WebUI/WebControl/IProperty.cs index b501aa7b..4a43d9b8 100644 --- a/src/WebExpress.WebUI/WebControl/IProperty.cs +++ b/src/WebExpress.WebUI/WebControl/IProperty.cs @@ -6,15 +6,15 @@ public interface IProperty { /// - /// Conversion to a CSS class. + /// Converts the property to a CSS class. /// - /// Die zur Eigenschaft gehârende CSS-KLasse + /// The CSS class corresponding to the property. string ToClass(); /// - /// Umwandlung in einen CSS-Style + /// Converts the property to a CSS style. /// - /// Der zur Eigenschaft gehârende CSS-Style + /// The CSS style corresponding to the property. public abstract string ToStyle(); } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyBorder.cs b/src/WebExpress.WebUI/WebControl/PropertyBorder.cs index f82ecfdc..229b0370 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyBorder.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyBorder.cs @@ -2,30 +2,33 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the border properties of a web control. + /// public class PropertyBorder : IProperty { /// - /// Der obere Abstand + /// Returns the top border. /// public bool Top { get; private set; } /// - /// Der untere Abstand + /// Returns te bottom border. /// public bool Bottom { get; private set; } /// - /// Der linke Abstand + /// Returns the left border. /// public bool Left { get; private set; } /// - /// Der rechte Abstand + /// Returns the right border. /// public bool Right { get; private set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with no borders. /// public PropertyBorder() { @@ -33,19 +36,19 @@ public PropertyBorder() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with uniform borders. /// - /// Bestimmt, ob ein einheitlicher Rahmen angezeigt werden soll + /// Determines whether to show a uniform border. public PropertyBorder(bool showBorder = true) { Top = Bottom = Left = Right = showBorder; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specified horizontal and vertical borders. /// - /// Der horzontale Rahmen - /// Der vertikale Rahmen + /// The horizontal border. + /// The vertical border. public PropertyBorder(bool horizontal, bool vertical) { Left = Right = horizontal; @@ -53,12 +56,12 @@ public PropertyBorder(bool horizontal, bool vertical) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specified borders for each side. /// - /// Der linke Rahmen - /// Der rechte Rahmen - /// Der obere Rahmen - /// Der untere Rahmen + /// The left border. + /// The right border. + /// The top border. + /// The bottom border. public PropertyBorder(bool left, bool right, bool top, bool bottom) { Left = left; @@ -68,9 +71,9 @@ public PropertyBorder(bool left, bool right, bool top, bool bottom) } /// - /// Conversion to a CSS class. + /// Converts the border properties to a CSS class. /// - /// Die zum Rahmen gehârende CSS-KLasse + /// The CSS class corresponding to the border properties. public string ToClass() { if (Top == Bottom && Top == Left && Top == Right && Top == false) @@ -124,9 +127,9 @@ public string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the border properties to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the border properties. public virtual string ToStyle() { return null; diff --git a/src/WebExpress.WebUI/WebControl/PropertyColor.cs b/src/WebExpress.WebUI/WebControl/PropertyColor.cs index ae8163fb..5564e27e 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColor.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColor.cs @@ -1,14 +1,18 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property that defines a color, which can be either a system-defined + /// color or a user-defined color. + /// public abstract class PropertyColor : IProperty where T : System.Enum { /// - /// Die Farbe + /// Returns the system-defined color. /// public T SystemColor { get; protected set; } /// - /// Die benutzerdefinierte Farbe + /// Returns the user-defined color. /// public string UserColor { get; protected set; } @@ -17,20 +21,18 @@ public abstract class PropertyColor : IProperty where T : System.Enum ///
                                                                                                                                                                                                                                                                                      public PropertyColor() { - } /// - /// Conversion to a CSS class. + /// Converts the color property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the color property. public abstract string ToClass(); /// - /// Umwandlung in einen CSS-Style + /// Converts the color property to a CSS style. /// - /// Das zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the color property. public abstract string ToStyle(); - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs index 99792e87..e897efca 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackground.cs @@ -1,9 +1,12 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for background color. + /// public class PropertyColorBackground : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the default color. /// public PropertyColorBackground() { @@ -11,18 +14,18 @@ public PropertyColorBackground() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorBackground(TypeColorBackground color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified user color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorBackground(string color) { SystemColor = (TypeColorBackground)TypeColor.User; @@ -30,9 +33,9 @@ public PropertyColorBackground(string color) } /// - /// Conversion to a CSS class. + /// Converts the background color property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the background color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -44,9 +47,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the background color property to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the background color. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) @@ -56,6 +59,5 @@ public override string ToStyle() return null; } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs index 5c23992a..393436db 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundAlert.cs @@ -1,11 +1,14 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for background color alerts. + /// public class PropertyColorBackgroundAlert : PropertyColorBackground { /// /// Initializes a new instance of the class. /// - /// Die Farbe + /// The background color. public PropertyColorBackgroundAlert(TypeColorBackground color) : base(color) { @@ -14,16 +17,16 @@ public PropertyColorBackgroundAlert(TypeColorBackground color) /// /// Initializes a new instance of the class. /// - /// Die Farbe + /// The background color. public PropertyColorBackgroundAlert(string color) : base(color) { } /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the background color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -35,9 +38,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the background color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the background color. public override string ToStyle() { return base.ToStyle(); diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs index 1b70f74d..efc02654 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundBadge.cs @@ -1,46 +1,79 @@ namespace WebExpress.WebUI.WebControl { - public class PropertyColorBackgroundBadge : PropertyColorBackground + /// + /// Represents a property for background color specifically for badges. + /// + /// + /// This class extends the class to provide + /// additional functionality for handling badge-specific background colors. + /// + public class PropertyColorBackgroundBadge : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified badge color. /// - /// Die Farbe - public PropertyColorBackgroundBadge(TypeColorBackground color) - : base(color) + /// The badge color. + public PropertyColorBackgroundBadge(TypeColorBackgroundBadge color) { + SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified badge color. /// - /// Die Farbe + /// The badge color. public PropertyColorBackgroundBadge(string color) - : base(color) { + SystemColor = (TypeColorBackgroundBadge)TypeColor.User; + UserColor = color; } /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class with an option to outline. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the button color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) { - return ((TypeColorBackgroundBadge)SystemColor).ToClass(); + return SystemColor.ToClass(); } return null; } /// - /// Umwandlung in einen CSS-Style + /// Converts the color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the button color. public override string ToStyle() { - return base.ToStyle(); + if ((TypeColor)SystemColor == TypeColor.User) + { + return "background:" + UserColor + ";"; + } + + return null; + } + + /// + /// Converts the color to a CSS style with an option to outline. + /// + /// Determines whether the background color is removed. + /// The CSS style corresponding to the button color. + public virtual string ToStyle(bool outline) + { + if ((TypeColor)SystemColor == TypeColor.User) + { + if (outline) + { + return "border-color:" + UserColor + ";"; + } + + return "background:" + UserColor + ";border-color:" + UserColor + ";"; + } + + return null; } } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs index 2ad53f4a..a4e450c5 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBackgroundList.cs @@ -1,29 +1,32 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a list of background colors for a property. + /// public class PropertyColorBackgroundList : PropertyColorBackground { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified color. /// - /// Die Farbe + /// The background color. public PropertyColorBackgroundList(TypeColorBackground color) : base(color) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified color. /// - /// Die Farbe + /// The background color. public PropertyColorBackgroundList(string color) : base(color) { } /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the background color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -35,9 +38,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the background color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the background color. public override string ToStyle() { return base.ToStyle(); diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs b/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs index 7cf77755..f71374d5 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorBorder.cs @@ -1,20 +1,23 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for border color, which can be converted to CSS class or style. + /// public class PropertyColorBorder : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorBorder(TypeColorBorder color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorBorder(string color) { SystemColor = (TypeColorBorder)TypeColor.User; @@ -22,9 +25,9 @@ public PropertyColorBorder(string color) } /// - /// Conversion to a CSS class. + /// Converts the border color property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the border color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,9 +39,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the border color property to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the border color. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) @@ -48,6 +51,5 @@ public override string ToStyle() return null; } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs b/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs index cb507080..d2929812 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorButton.cs @@ -1,20 +1,23 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for button colors, allowing conversion to CSS classes and styles. + /// public class PropertyColorButton : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorButton(TypeColorButton color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorButton(string color) { SystemColor = (TypeColorButton)TypeColor.User; @@ -22,9 +25,9 @@ public PropertyColorButton(string color) } /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the button color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,10 +39,10 @@ public override string ToClass() } /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class with an option to outline. /// - /// Bestimmt ob die Hintergrundfarbe entfernt wird - /// Die zur Farbe gehârende CSS-KLasse + /// Determines whether the background color is removed. + /// The CSS class corresponding to the button color. public virtual string ToClass(bool outline) { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -51,9 +54,9 @@ public virtual string ToClass(bool outline) } /// - /// Umwandlung in einen CSS-Style + /// Converts the color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the button color. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) @@ -65,10 +68,10 @@ public override string ToStyle() } /// - /// Umwandlung in einen CSS-Style + /// Converts the color to a CSS style with an option to outline. /// - /// Bestimmt ob die Hintergrundfarbe entfernt wird - /// Der zur Farbe gehârende CSS-Style + /// Determines whether the background color is removed. + /// The CSS style corresponding to the button color. public virtual string ToStyle(bool outline) { if ((TypeColor)SystemColor == TypeColor.User) @@ -83,6 +86,5 @@ public virtual string ToStyle(bool outline) return null; } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs b/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs index 1184d218..d9e4571a 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorCallout.cs @@ -1,20 +1,26 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property color callout which is a specific type of PropertyColor. + /// + /// + /// This class provides functionality to convert the color to a CSS class or style. + /// public class PropertyColorCallout : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorCallout(TypeColorCallout color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorCallout(string color) { SystemColor = (TypeColorCallout)TypeColor.User; @@ -22,9 +28,9 @@ public PropertyColorCallout(string color) } /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the badge color, or null if the color is default or user-defined. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,9 +42,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the progress color, or null if the color is not user-defined. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) @@ -48,6 +54,5 @@ public override string ToStyle() return null; } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs b/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs index 0cd60ac8..25941a74 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorChart.cs @@ -1,9 +1,12 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property color chart that can be converted to CSS classes or styles. + /// public class PropertyColorChart : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the default color. /// public PropertyColorChart() { @@ -11,18 +14,18 @@ public PropertyColorChart() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorChart(TypeColorChart color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified user-defined color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorChart(string color) { SystemColor = (TypeColorChart)TypeColor.User; @@ -30,27 +33,27 @@ public PropertyColorChart(string color) } /// - /// Conversion to a CSS class. + /// Converts the property color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the badge color. public override string ToClass() { return null; } /// - /// Umwandlung in einen CSS-Style + /// Converts the property color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the progress color. public override string ToStyle() { return null; } /// - /// Conversion to a CSS class. + /// Converts the property color to a string representation. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class or user-defined color as a string. public override string ToString() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs b/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs index 0fb649de..cf77afeb 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorLine.cs @@ -1,20 +1,23 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property color line that can be converted to CSS classes or styles. + /// public class PropertyColorLine : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorLine(TypeColorLine color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user-defined color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorLine(string color) { SystemColor = (TypeColorLine)TypeColor.User; @@ -22,9 +25,9 @@ public PropertyColorLine(string color) } /// - /// Conversion to a CSS class. + /// Converts the property color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the badge color, or null if the color is default or user-defined. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,9 +39,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the property color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the progress color, or null if the color is not user-defined. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) @@ -48,6 +51,5 @@ public override string ToStyle() return null; } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs b/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs index 16630a5e..05e50b70 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorNavbar.cs @@ -1,20 +1,23 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for the color of a navbar. + /// public class PropertyColorNavbar : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorNavbar(TypeColorNavbar color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorNavbar(string color) { SystemColor = (TypeColorNavbar)TypeColor.User; @@ -22,9 +25,9 @@ public PropertyColorNavbar(string color) } /// - /// Conversion to a CSS class. + /// Converts the color property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the navbar color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,9 +39,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the color property to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the navbar color. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs b/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs index 24f29afe..b7b2968b 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorProgress.cs @@ -1,20 +1,23 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property color for progress elements. + /// public class PropertyColorProgress : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified color. /// - /// Die Farbe + /// The color to be used for the progress element. public PropertyColorProgress(TypeColorProgress color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified color. /// - /// Die Farbe + /// The color to be used for the progress element. public PropertyColorProgress(string color) { SystemColor = (TypeColorProgress)TypeColor.User; @@ -24,7 +27,7 @@ public PropertyColorProgress(string color) /// /// Conversion to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the badge color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -36,17 +39,19 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Conversion to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the progress color. public override string ToStyle() { - if ((TypeColor)SystemColor == TypeColor.User) { - return "background:" + UserColor + ";"; - } + if ((TypeColor)SystemColor == TypeColor.User) + { + return "background:" + UserColor + ";"; + } - return null; + return null; + } } } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyColorText.cs b/src/WebExpress.WebUI/WebControl/PropertyColorText.cs index e47e630d..1c2d5e22 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyColorText.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyColorText.cs @@ -1,9 +1,12 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for text color. + /// public class PropertyColorText : PropertyColor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the default color. /// public PropertyColorText() { @@ -11,18 +14,18 @@ public PropertyColorText() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified system color. /// - /// Die Farbe + /// The system color. public PropertyColorText(TypeColorText color) { SystemColor = color; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified user-defined color. /// - /// Die Farbe + /// The user-defined color. public PropertyColorText(string color) { SystemColor = (TypeColorText)TypeColor.User; @@ -30,9 +33,9 @@ public PropertyColorText(string color) } /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the color. public override string ToClass() { if ((TypeColor)SystemColor != TypeColor.Default && (TypeColor)SystemColor != TypeColor.User) @@ -44,9 +47,9 @@ public override string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the color to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the color. public override string ToStyle() { if ((TypeColor)SystemColor == TypeColor.User) diff --git a/src/WebExpress.WebUI/WebControl/PropertyGrid.cs b/src/WebExpress.WebUI/WebControl/PropertyGrid.cs index 6dde8921..b04adcc8 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyGrid.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyGrid.cs @@ -1,15 +1,18 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property grid that can be used to define properties for a web control. + /// public class PropertyGrid : IProperty { /// - /// Liefert oder setzt das zu verwendende AnzeigegerÀt + /// Returns the device type to be used. /// public TypeDevice Device { get; private set; } /// - /// Die Anzahl der verwendeten Spalten - /// Hinweis: Alle Spalten innerhalb eines PannelGrids muss die Summer 12 ergeben! + /// Returns the number of columns used. + /// Note: All columns within a PanelGrid must sum up to 12! /// public int Columns { get; private set; } @@ -24,8 +27,8 @@ public PropertyGrid() /// /// Initializes a new instance of the class. /// - /// Bestimmt, ob ein einheitlicher Rahmen angezeigt werden soll - /// Die Anzahl der verwendeten Spalten. Hinweis: Alle Spalten innerhalb eines PannelGrids muss die Summer 12 ergeben! + /// Determines whether a uniform frame should be displayed. + /// The number of columns used. Note: All columns within a PanelGrid must sum up to 12! public PropertyGrid(TypeDevice device, int columns) { Device = device; @@ -33,9 +36,9 @@ public PropertyGrid(TypeDevice device, int columns) } /// - /// Conversion to a CSS class. + /// Converts the property to a CSS class. /// - /// Die zum Rahmen gehârende CSS-KLasse + /// The CSS class corresponding to the property. public string ToClass() { return Device switch @@ -51,9 +54,9 @@ public string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the property to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the property. public virtual string ToStyle() { return null; diff --git a/src/WebExpress.WebUI/WebControl/PropertyIcon.cs b/src/WebExpress.WebUI/WebControl/PropertyIcon.cs index cd584065..051523a8 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyIcon.cs @@ -1,35 +1,39 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents an icon property that can be either a system-defined icon or a user-defined icon. + /// public class PropertyIcon : IProperty { /// - /// Das System-Icon + /// Returns the system icon. /// public TypeIcon SystemIcon { get; protected set; } /// - /// Das benutzerdefinierte Icon + /// Returns te user-defined icon. /// public string UserIcon { get; protected set; } /// - /// Die Grâße des Icons (nur bei Benutzerdefinierten Icons) + /// Returns the size of the icon (only for user-defined icons). /// public PropertySizeIcon Size { get; protected set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a system icon. /// - /// Das System-Icon + /// The system icon. public PropertyIcon(TypeIcon icon) { SystemIcon = icon; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a user-defined icon. /// - /// Das benutzerdefinierte Icon + /// The user-defined icon. + /// The size of the icon. public PropertyIcon(string icon, PropertySizeIcon size = null) { SystemIcon = TypeIcon.None; @@ -38,9 +42,9 @@ public PropertyIcon(string icon, PropertySizeIcon size = null) } /// - /// Conversion to a CSS class. + /// Converts the icon to a CSS class. /// - /// Die zum Icon gehârende CSS-KLasse + /// The CSS class corresponding to the icon. public virtual string ToClass() { if (SystemIcon != TypeIcon.None) @@ -52,9 +56,9 @@ public virtual string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the icon to a CSS style. /// - /// Das zum Icon gehârende CSS-Style + /// The CSS style corresponding to the icon. public virtual string ToStyle() { if (SystemIcon == TypeIcon.None) @@ -66,15 +70,15 @@ public virtual string ToStyle() } /// - /// Prüft ob ein Icon gesetzt ist + /// Checks if an icon is set. /// - /// True wenn ein Icon gesetzt ist, false sonst + /// True if an icon is set, false otherwise. public virtual bool HasIcon => SystemIcon != TypeIcon.None || UserIcon != null; /// - /// Prüft ob ein benutzerdefiniertes Icon gesetzt ist + /// Checks if a user-defined icon is set. /// - /// True wenn ein benutzerdefiniertes Icon gesetzt ist, false sonst + /// True if a user-defined icon is set, false otherwise. public virtual bool IsUserIcon => UserIcon != null; } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs b/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs index 6cbf6987..c6f273ac 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyMaxSizeIcon.cs @@ -2,42 +2,45 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the maximum size properties of an icon, including width, height, and unit. + /// public class PropertyMaxSizeIcon : PropertySizeIcon { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a specified size and unit. /// - /// Die Grâße - /// Die Einheit + /// The size of the icon. + /// The unit of the size. public PropertyMaxSizeIcon(int size, TypeSizeUnit unit) : base(size, unit) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specified width, height, and unit. /// - /// Die Weite in Pixel - /// Die Hâhe in Pixel - /// Die Einheit + /// The width of the icon in pixels. + /// The height of the icon in pixels. + /// The unit of the size. public PropertyMaxSizeIcon(int width, int height, TypeSizeUnit unit) : base(width, height, unit) { } /// - /// Conversion to a CSS class. + /// Converts the property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the property. public override string ToClass() { return null; } /// - /// Umwandlung in einen CSS-Style + /// Converts the property to a CSS style. /// - /// Das zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the property. public override string ToStyle() { var style = new StringBuilder(); @@ -63,6 +66,5 @@ public override string ToStyle() return style.ToString(); } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertyModal.cs b/src/WebExpress.WebUI/WebControl/PropertyModal.cs index 4b176d4e..48789254 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyModal.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyModal.cs @@ -6,27 +6,27 @@ public class PropertyModal { /// - /// The modal type. + /// Returns the modal type. /// public TypeModal Type { get; protected set; } /// - /// The custom modal. + /// Returns the custom modal. /// public ControlModal Modal { get; protected set; } /// - /// The size of the modal. + /// Returns the size of the modal. /// public TypeModalSize Size { get; protected set; } /// - /// The uri. + /// Returns the uri. /// public string Uri { get; protected set; } /// - /// The forwarding uri. + /// Returns the forwarding uri. /// public string RedirectUri { get; set; } @@ -57,7 +57,7 @@ public PropertyModal(TypeModal type, TypeModalSize size = TypeModalSize.Default) /// /// Initializes a new instance of the class. /// - /// The modal type + /// The modal type. /// Custom modal or null. /// The size of the modal. public PropertyModal(TypeModal type, ControlModal modal, TypeModalSize size = TypeModalSize.Default) @@ -71,7 +71,7 @@ public PropertyModal(TypeModal type, ControlModal modal, TypeModalSize size = Ty /// /// Initializes a new instance of the class. /// - /// The modal type + /// The modal type. /// The uri. /// The size of the modal. public PropertyModal(TypeModal type, string uri, TypeModalSize size = TypeModalSize.Default) diff --git a/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs b/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs index fb5a7e31..70d2b77d 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyOnChange.cs @@ -1,30 +1,33 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property that changes based on system or user-defined values. + /// public class PropertyOnChange { /// - /// Der System-Wert + /// Returns the system value. /// public TypeOnChange SystemValue { get; protected set; } /// - /// Der benutzerdefinierte Wert + /// Returns the user-defined value. /// public string UserValue { get; protected set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a system value. /// - /// Der System-Wert + /// The system value. public PropertyOnChange(TypeOnChange value) { SystemValue = value; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a user-defined value. /// - /// Der benutzerdefinierte Wert + /// The user-defined value. public PropertyOnChange(string value) { SystemValue = TypeOnChange.None; @@ -32,9 +35,9 @@ public PropertyOnChange(string value) } /// - /// Conversion to string. + /// Converts the value to its string representation. /// - /// Die StringreprÀsentation + /// The string representation of the value. public override string ToString() { if (SystemValue != TypeOnChange.None) diff --git a/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs b/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs index 364e0066..ed2d476f 100644 --- a/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs +++ b/src/WebExpress.WebUI/WebControl/PropertyOnClick.cs @@ -1,30 +1,33 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property that handles the OnClick event. + /// public class PropertyOnClick { /// - /// Der System-Wert + /// Returns the system value. /// public TypeOnChange SystemValue { get; protected set; } /// - /// Der benutzerdefinierte Wert + /// Returns the user-defined value. /// public string Value { get; protected set; } /// /// Initializes a new instance of the class. /// - /// Der benutzerdefinierte Wert + /// The user-defined value. public PropertyOnClick(string value) { Value = value; } /// - /// Conversion to string. + /// Returns a string that represents the current object. /// - /// Die StringreprÀsentation + /// A string that represents the current object. public override string ToString() { return Value; diff --git a/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs b/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs index ede77437..ee28e0c9 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySizeIcon.cs @@ -2,28 +2,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the size properties of an icon, including width, height, and unit. + /// public class PropertySizeIcon : IProperty { /// - /// Die Einhelten + /// Gets the unit of measurement for the size. /// public TypeSizeUnit Unit { get; protected set; } = TypeSizeUnit.Pixel; /// - /// Die System-Grâße + /// Gets the width of the icon. /// public int Width { get; protected set; } = -1; /// - /// Die benutzerdefinierte Grâße + /// Gets the height of the icon. /// public int Height { get; protected set; } = -1; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the same width and height. /// - /// Die Grâße - /// Die Einheit + /// The size of the icon. + /// The unit of measurement for the size. public PropertySizeIcon(int size, TypeSizeUnit unit) { Width = size; @@ -32,11 +35,11 @@ public PropertySizeIcon(int size, TypeSizeUnit unit) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specified width and height. /// - /// Die Weite in Pixel - /// Die Hâhe in Pixel - /// Die Einheit + /// The width of the icon. + /// The height of the icon. + /// The unit of measurement for the size. public PropertySizeIcon(int width, int height, TypeSizeUnit unit) { Width = width; @@ -45,18 +48,18 @@ public PropertySizeIcon(int width, int height, TypeSizeUnit unit) } /// - /// Conversion to a CSS class. + /// Converts the size properties to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class representing the size properties. public virtual string ToClass() { return null; } /// - /// Umwandlung in einen CSS-Style + /// Converts the size properties to a CSS style. /// - /// Das zur Farbe gehârende CSS-Style + /// The CSS style representing the size properties. public virtual string ToStyle() { var style = new StringBuilder(); @@ -82,6 +85,5 @@ public virtual string ToStyle() return style.ToString(); } - } } diff --git a/src/WebExpress.WebUI/WebControl/PropertySizeText.cs b/src/WebExpress.WebUI/WebControl/PropertySizeText.cs index 5c952250..f254f132 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySizeText.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySizeText.cs @@ -2,31 +2,34 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents a property for text size, which can be either a predefined system size or a custom user-defined size. + /// public class PropertySizeText : IProperty { /// - /// Die System-Grâße + /// Returns the system-defined size. /// public TypeSizeText SystemSize { get; protected set; } /// - /// Die benutzerdefinierte Grâße + /// Returns the user-defined size in REM. /// public float? UserSize { get; protected set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a system-defined size. /// - /// Die System-Grâße + /// The system-defined size. public PropertySizeText(TypeSizeText size) { SystemSize = size; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a user-defined size in REM. /// - /// Das benutzerdefinierte Grâße in REM + /// The user-defined size in REM. public PropertySizeText(float size) { SystemSize = TypeSizeText.Default; @@ -34,9 +37,9 @@ public PropertySizeText(float size) } /// - /// Conversion to a CSS class. + /// Converts the property to a CSS class. /// - /// Die zur Farbe gehârende CSS-KLasse + /// The CSS class corresponding to the size. public virtual string ToClass() { if (SystemSize != TypeSizeText.Default) @@ -48,9 +51,9 @@ public virtual string ToClass() } /// - /// Umwandlung in einen CSS-Style + /// Converts the property to a CSS style. /// - /// Das zur Farbe gehârende CSS-Style + /// The CSS style corresponding to the size. public virtual string ToStyle() { if (SystemSize != TypeSizeText.Default) @@ -66,15 +69,15 @@ public virtual string ToStyle() } /// - /// Prüft ob ein Icon gesetzt ist + /// Gets a value indicating whether a size is set. /// - /// True wenn ein Icon gesetzt ist, false sonst + /// True if a size is set, false otherwise. public virtual bool HasSize => SystemSize != TypeSizeText.Default || UserSize.HasValue; /// - /// Prüft ob ein benutzerdefiniertes Icon gesetzt ist + /// Gets a value indicating whether a user-defined size is set. /// - /// True wenn ein benutzerdefiniertes Icon gesetzt ist, false sonst + /// True if a user-defined size is set, false otherwise. public virtual bool IsUserSize => SystemSize == TypeSizeText.Default && UserSize.HasValue; } } diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacing.cs b/src/WebExpress.WebUI/WebControl/PropertySpacing.cs index d9aa963f..c38deb18 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacing.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacing.cs @@ -1,29 +1,32 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the spacing properties for a web control. + /// public abstract class PropertySpacing : IProperty { /// - /// Die mâglichen AbstÀnde + /// The possible spacing values. /// public enum Space { None, Null, One, Two, Three, Four, Five, Auto }; /// - /// Der obere Abstand + /// Returns the top spacing. /// public Space Top { get; private set; } /// - /// Der untere Abstand + /// Returns the bottom spacing. /// public Space Bottom { get; private set; } /// - /// Der linke Abstand + /// Returns the left spacing. /// public Space Left { get; private set; } /// - /// Der rechte Abstand + /// Returns the right spacing. /// public Space Right { get; private set; } @@ -36,19 +39,19 @@ public PropertySpacing() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the same spacing for all sides. /// - /// Die AbstÀnde + /// The spacing size for all sides. public PropertySpacing(Space size) { Top = Bottom = Left = Right = size; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with different horizontal and vertical spacing. /// - /// Der horzontale Abstand - /// Der vertikale Abstand + /// The horizontal spacing. + /// The vertical spacing. public PropertySpacing(Space horizontal, Space vertical) { Left = Right = horizontal; @@ -56,12 +59,12 @@ public PropertySpacing(Space horizontal, Space vertical) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specific spacing for each side. /// - /// Der linke Abstand - /// Der rechte Abstand - /// Der obere Abstand - /// Der untere Abstand + /// The left spacing. + /// The right spacing. + /// The top spacing. + /// The bottom spacing. public PropertySpacing(Space left, Space right, Space top, Space bottom) { Left = left; @@ -71,10 +74,10 @@ public PropertySpacing(Space left, Space right, Space top, Space bottom) } /// - /// Konvertiert eine Abstandsangabe in einen String + /// Converts a spacing value to its string representation. /// - /// - /// Die StringreprÀsentation + /// The spacing value. + /// The string representation of the spacing value. protected static string ConvertSize(Space size) { return size switch @@ -91,9 +94,10 @@ protected static string ConvertSize(Space size) } /// - /// Conversion to a CSS class. + /// Converts the spacing values to a CSS class. /// - /// The CSS class belonging to the layout + /// The prefix for the CSS class. + /// The CSS class representing the spacing values. protected string ToClass(string prefix) { if (Top == Bottom && Top == Left && Top == Right && Top == Space.None) @@ -184,13 +188,13 @@ protected string ToClass(string prefix) /// /// Conversion to a CSS class. /// - /// Die zum Spacing gehârende CSS-KLasse + /// The CSS class representing the spacing. public abstract string ToClass(); /// - /// Umwandlung in einen CSS-Style + /// Conversion to a CSS style. /// - /// Der zur Farbe gehârende CSS-Style + /// The CSS style representing the spacing. public virtual string ToStyle() { return null; diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs b/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs index baf14ac8..026b1829 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacingMargin.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the margin spacing properties for a web control. + /// public class PropertySpacingMargin : PropertySpacing { /// @@ -11,40 +14,40 @@ public PropertySpacingMargin() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the same spacing for all sides. /// - /// Die AbstÀnde + /// The spacing size for all sides. public PropertySpacingMargin(Space size) : base(size) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with different horizontal and vertical spacing. /// - /// Der horzontale Abstand - /// Der vertikale Abstand + /// The horizontal spacing. + /// The vertical spacing. public PropertySpacingMargin(Space horizontal, Space vertical) : base(horizontal, vertical) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specific spacing for each side. /// - /// Der linke Abstand - /// Der rechte Abstand - /// Der obere Abstand - /// Der untere Abstand + /// The left spacing. + /// The right spacing. + /// The top spacing. + /// The bottom spacing. public PropertySpacingMargin(Space left, Space right, Space top, Space bottom) : base(left, right, top, bottom) { } /// - /// Conversion to a CSS class. + /// Converts the margin spacing values to a CSS class. /// - /// The CSS class belonging to the layout + /// The CSS class representing the margin spacing. public override string ToClass() { return ToClass("m"); diff --git a/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs b/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs index b7a48896..7ded610a 100644 --- a/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs +++ b/src/WebExpress.WebUI/WebControl/PropertySpacingPadding.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the padding properties for a web control. + /// public class PropertySpacingPadding : PropertySpacing { /// @@ -11,40 +14,40 @@ public PropertySpacingPadding() } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the same padding for all sides. /// - /// Die AbstÀnde + /// The padding size for all sides. public PropertySpacingPadding(Space size) : base(size) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with different horizontal and vertical padding. /// - /// Der horzontale Abstand - /// Der vertikale Abstand + /// The horizontal padding. + /// The vertical padding. public PropertySpacingPadding(Space horizontal, Space vertical) : base(horizontal, vertical) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with specific padding for each side. /// - /// Der linke Abstand - /// Der rechte Abstand - /// Der obere Abstand - /// Der untere Abstand + /// The left padding. + /// The right padding. + /// The top padding. + /// The bottom padding. public PropertySpacingPadding(Space left, Space right, Space top, Space bottom) : base(left, right, top, bottom) { } /// - /// Conversion to a CSS class. + /// Converts the padding values to a CSS class. /// - /// The CSS class belonging to the layout + /// The CSS class representing the padding values. public override string ToClass() { return ToClass("p"); diff --git a/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs index 60f28f8d..ceded732 100644 --- a/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs +++ b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs @@ -10,7 +10,7 @@ namespace WebExpress.WebUI.WebControl /// public class RenderControlFormContext : RenderControlContext, IRenderControlFormContext { - private readonly IList _validationResults = []; + private readonly List _validationResults = []; /// /// The form in which the control is rendered. diff --git a/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs b/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs index 1e1a3664..0b7e30a1 100644 --- a/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs +++ b/src/WebExpress.WebUI/WebControl/RenderControlFormGroupContext.cs @@ -6,7 +6,7 @@ public class RenderControlFormGroupContext : RenderControlFormContext, IRenderControlFormGroupContext { /// - /// Die Gruppe, indem das Steuerelement gerendert wird + /// Returns the group in which the control is rendered. /// public ControlFormItemGroup Group { get; private set; } @@ -14,7 +14,7 @@ public class RenderControlFormGroupContext : RenderControlFormContext, IRenderCo /// Initializes a new instance of the class. /// /// The context in which the control is rendered. - /// Die Gruppe + /// The group in which the control is rendered. public RenderControlFormGroupContext(IRenderControlFormContext context, ControlFormItemGroup group) : base(context) { diff --git a/src/WebExpress.WebUI/WebControl/TypeActive.cs b/src/WebExpress.WebUI/WebControl/TypeActive.cs index 0e9c7664..efc9d413 100644 --- a/src/WebExpress.WebUI/WebControl/TypeActive.cs +++ b/src/WebExpress.WebUI/WebControl/TypeActive.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the active state of a web control. + /// public enum TypeActive { + /// + /// No active state. + /// None, + + /// + /// The control is active. + /// Active, + + /// + /// The control is disabled. + /// Disabled } + /// + /// Provides extension methods for the enum. + /// public static class TypesActiveExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeActive layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeAlignFlexbox.cs b/src/WebExpress.WebUI/WebControl/TypeAlignFlexbox.cs index 5cda021a..8ed9a77a 100644 --- a/src/WebExpress.WebUI/WebControl/TypeAlignFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/TypeAlignFlexbox.cs @@ -1,22 +1,51 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the alignment of flexbox items. + /// public enum TypeAlignFlexbox { + /// + /// No alignment. + /// None, + + /// + /// Items are packed toward the start of the flex container. + /// Start, + + /// + /// Items are packed toward the end of the flex container. + /// End, + + /// + /// Items are centered in the flex container. + /// Center, + + /// + /// Items are aligned such that their baselines align. + /// Baseline, + + /// + /// Items are stretched to fill the flex container. + /// Stretch } + /// + /// Provides extension methods for the enum. + /// public static class TypeAlignFlexboxExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeAlignFlexbox layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeAlignmentDropdownMenu.cs b/src/WebExpress.WebUI/WebControl/TypeAlignmentDropdownMenu.cs index 0ab864e1..b31d85a5 100644 --- a/src/WebExpress.WebUI/WebControl/TypeAlignmentDropdownMenu.cs +++ b/src/WebExpress.WebUI/WebControl/TypeAlignmentDropdownMenu.cs @@ -1,21 +1,31 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Anordnungsmâglichkeiten + /// The alignment options for the dropdown menu. /// public enum TypeAlignmentDropdownMenu { + /// + /// Default alignment. + /// Default, + + /// + /// Align to the right. + /// Right } + /// + /// Extension methods for the enum. + /// public static class TypeAlighmentDropdownMenuExtensions { /// - /// Conversion to a CSS class. + /// Converts the alignment option to a CSS class. /// - /// Die Anordnung, welches umgewandelt werden soll - /// Die zur Anordnung gehârende CSS-KLasse + /// The alignment option to convert. + /// The corresponding CSS class for the alignment option. public static string ToClass(this TypeAlignmentDropdownMenu direction) { return direction switch diff --git a/src/WebExpress.WebUI/WebControl/TypeBlockButton.cs b/src/WebExpress.WebUI/WebControl/TypeBlockButton.cs index b0d62396..b03e896c 100644 --- a/src/WebExpress.WebUI/WebControl/TypeBlockButton.cs +++ b/src/WebExpress.WebUI/WebControl/TypeBlockButton.cs @@ -1,21 +1,31 @@ namespace WebExpress.WebUI.WebControl { /// - /// Spannt die SchaltflÀche über die gesammte Bereite + /// Specifies the type of block button. /// public enum TypeBlockButton { + /// + /// No block button. + /// None, + + /// + /// Block button that spans the entire width. + /// Block } + /// + /// Provides extension methods for the enum. + /// public static class TypeBlockButtonExtensions { /// - /// Conversion to a CSS class. + /// Converts the block button type to a corresponding CSS class. /// - /// Der Wert, welches umgewandelt werden soll - /// Die zum Block gehârende CSS-KLasse + /// The block button type to convert. + /// The CSS class corresponding to the block button type. public static string ToClass(this TypeBlockButton block) { return block switch diff --git a/src/WebExpress.WebUI/WebControl/TypeButton.cs b/src/WebExpress.WebUI/WebControl/TypeButton.cs index 32cfec99..bfc06756 100644 --- a/src/WebExpress.WebUI/WebControl/TypeButton.cs +++ b/src/WebExpress.WebUI/WebControl/TypeButton.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the type of a button. + /// public enum TypeButton { + /// + /// Default button type. + /// Default = 0, // Button + + /// + /// Submit button type. + /// Submit = 1, + + /// + /// Reset button type. + /// Reset = 2 } + /// + /// Provides extension methods for the enum. + /// public static class TypeButtonExtensions { /// - /// Conversion to string. + /// Converts the button type to its corresponding string representation. /// - /// Der Typ - /// Der String + /// The button type. + /// The string representation of the button type. public static string ToTypeString(this TypeButton type) { switch (type) @@ -21,7 +38,7 @@ public static string ToTypeString(this TypeButton type) case TypeButton.Submit: return "submit"; case TypeButton.Reset: - return "submit"; + return "reset"; } return "button"; diff --git a/src/WebExpress.WebUI/WebControl/TypeChart.cs b/src/WebExpress.WebUI/WebControl/TypeChart.cs index bb1efe6b..08a54066 100644 --- a/src/WebExpress.WebUI/WebControl/TypeChart.cs +++ b/src/WebExpress.WebUI/WebControl/TypeChart.cs @@ -1,22 +1,48 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration representing different types of charts. + /// public enum TypeChart { + /// + /// Line chart type. + /// Line = 0, + + /// + /// Bar chart type. + /// Bar = 1, + + /// + /// Pie chart type. + /// Pie = 2, + + /// + /// Doughnut chart type. + /// Doughnut = 3, - //Polar = 4, + + // Polar = 4, + + /// + /// Radar chart type. + /// Radar = 5 } + /// + /// Extension methods for the enumeration. + /// public static class TypeChartExtensions { /// - /// Conversion to a CSS class. + /// Converts the chart type to a corresponding CSS class. /// - /// Die Farbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The chart type to be converted. + /// The CSS class corresponding to the chart type. public static string ToType(this TypeChart color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColor.cs b/src/WebExpress.WebUI/WebControl/TypeColor.cs index cc881335..b05f5a99 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColor.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColor.cs @@ -1,32 +1,86 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Standardhintergrundfarben + /// The standard background colors. /// public enum TypeColor { + /// + /// Default color. + /// Default = 0, + + /// + /// Primary color. + /// Primary = 1, + + /// + /// Secondary color. + /// Secondary = 2, + + /// + /// Success color. + /// Success = 3, + + /// + /// Info color. + /// Info = 4, + + /// + /// Warning color. + /// Warning = 5, + + /// + /// Danger color. + /// Danger = 6, + + /// + /// Dark color. + /// Dark = 7, + + /// + /// Light color. + /// Light = 8, + + /// + /// White color. + /// White = 9, + + /// + /// Transparent color. + /// Transparent = 10, + + /// + /// Mute color. + /// Mute = 11, + + /// + /// User-defined color. + /// User = 12 } + /// + /// Extension methods for the enum. + /// public static class TypeColorExtensions { /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die Hintergrundfarbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The background color to be converted. + /// The CSS class corresponding to the background color. public static string ToClass(this TypeColor color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorBackground.cs b/src/WebExpress.WebUI/WebControl/TypeColorBackground.cs index d913c592..9ce56d31 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorBackground.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorBackground.cs @@ -1,30 +1,76 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Standardhintergrundfarben + /// The standard background colors. /// public enum TypeColorBackground { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + + /// + /// Light background color. + /// Light = 8, + + /// + /// White background color. + /// White = 9, + + /// + /// Transparent background color. + /// Transparent = 10 } + /// + /// Provides extension methods for the enum. + /// public static class TypeColorBackgroundExtensions { /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die Hintergrundfarbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The background color to convert. + /// The CSS class corresponding to the background color. public static string ToClass(this TypeColorBackground color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundAlert.cs b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundAlert.cs index 2fa9e438..731a921a 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundAlert.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundAlert.cs @@ -1,27 +1,76 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the different types of background colors for alerts. + /// public enum TypeColorBackgroundAlert { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + + /// + /// Light background color. + /// Light = 8, + + /// + /// White background color. + /// White = 9, + + /// + /// Transparent background color. + /// Transparent = 10 } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeColorBackgroundAlertExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeColorBackgroundAlert layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundBadge.cs b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundBadge.cs index 57df66d5..a7222df8 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundBadge.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundBadge.cs @@ -1,20 +1,68 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration for different types of background colors for badges. + /// public enum TypeColorBackgroundBadge { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + /// + /// Light background color. + /// Light = 8, + + /// + /// White background color. + /// White = 9, + + /// + /// Transparent background color. + /// Transparent = 10 } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeColorBackgroundBadgeExtensions { /// diff --git a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundList.cs b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundList.cs index 49035597..73ce4052 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorBackgroundList.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorBackgroundList.cs @@ -1,20 +1,69 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration for different background color types for a list. + /// public enum TypeColorBackgroundList { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + + /// + /// Light background color. + /// Light = 8, + + /// + /// White background color. + /// White = 9, + + /// + /// Transparent background color. + /// Transparent = 10 } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeColorBackgroundListExtensions { /// diff --git a/src/WebExpress.WebUI/WebControl/TypeColorBorder.cs b/src/WebExpress.WebUI/WebControl/TypeColorBorder.cs index c42eae3e..081ec451 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorBorder.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorBorder.cs @@ -1,27 +1,76 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration for different types of border colors. + /// public enum TypeColorBorder { + /// + /// Default border color. + /// Default = 0, + + /// + /// Primary border color. + /// Primary = 1, + + /// + /// Secondary border color. + /// Secondary = 2, + + /// + /// Success border color. + /// Success = 3, + + /// + /// Info border color. + /// Info = 4, + + /// + /// Warning border color. + /// Warning = 5, + + /// + /// Danger border color. + /// Danger = 6, + + /// + /// Dark border color. + /// Dark = 7, + + /// + /// Light border color. + /// Light = 8, + + /// + /// White border color. + /// White = 9, + + /// + /// Transparent border color. + /// Transparent = 10 } + /// + /// Extension methods for the enumeration. + /// public static class TypeColorBorderExtensions { /// - /// Conversion to a CSS class. + /// Converts the to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The border color type to be converted. + /// The CSS class corresponding to the border color type. public static string ToClass(this TypeColorBorder layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorButton.cs b/src/WebExpress.WebUI/WebControl/TypeColorButton.cs index 56157c4a..6f375b03 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorButton.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorButton.cs @@ -5,19 +5,54 @@ /// public enum TypeColorButton { + /// + /// Default button color. + /// Default = 0, + + /// + /// Primary button color. + /// Primary = 1, + + /// + /// Secondary button color. + /// Secondary = 2, + + /// + /// Success button color. + /// Success = 3, + + /// + /// Info button color. + /// Info = 4, + + /// + /// Warning button color. + /// Warning = 5, + + /// + /// Danger button color. + /// Danger = 6, + + /// + /// Dark button color. + /// Dark = 7, + + /// + /// Light button color. + /// Light = 8 } /// - /// Provides extension methods for the TypeColorButton enumeration. + /// Provides extension methods for the enumeration. /// public static class TypeColorButtonExtensions { diff --git a/src/WebExpress.WebUI/WebControl/TypeColorCallout.cs b/src/WebExpress.WebUI/WebControl/TypeColorCallout.cs index 79a52fd8..51f0868f 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorCallout.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorCallout.cs @@ -1,25 +1,66 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration representing different types of color callouts. + /// public enum TypeColorCallout { + /// + /// Default color callout. + /// Default = 0, + + /// + /// Primary color callout. + /// Primary = 1, + + /// + /// Secondary color callout. + /// Secondary = 2, + + /// + /// Success color callout. + /// Success = 3, + + /// + /// Info color callout. + /// Info = 4, + + /// + /// Warning color callout. + /// Warning = 5, + + /// + /// Danger color callout. + /// Danger = 6, + + /// + /// Dark color callout. + /// Dark = 7, + + /// + /// Light color callout. + /// Light = 8 } + /// + /// Extension methods for the enumeration. + /// public static class TypeColorCalloutExtensions { /// - /// Conversion to a CSS class. + /// Converts the TypeColorCallout to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The TypeColorCallout to be converted. + /// The CSS class corresponding to the TypeColorCallout. public static string ToClass(this TypeColorCallout layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorChart.cs b/src/WebExpress.WebUI/WebControl/TypeColorChart.cs index e0bc6996..f6405a01 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorChart.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorChart.cs @@ -1,25 +1,66 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the different types of color charts. + /// public enum TypeColorChart { + /// + /// Default color. + /// Default = 0, + + /// + /// Primary color. + /// Primary = 1, + + /// + /// Secondary color. + /// Secondary = 2, + + /// + /// Success color. + /// Success = 3, + + /// + /// Info color. + /// Info = 4, + + /// + /// Warning color. + /// Warning = 5, + + /// + /// Danger color. + /// Danger = 6, + + /// + /// Dark color. + /// Dark = 7, + + /// + /// Light color. + /// Light = 8 } + /// + /// Provides extension methods for the enum. + /// public static class TypeColorChartExtensions { /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class. /// - /// Die Farbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The color to be converted. + /// The CSS class corresponding to the color. public static string ToChartColor(this TypeColorChart color) { switch (color) diff --git a/src/WebExpress.WebUI/WebControl/TypeColorLine.cs b/src/WebExpress.WebUI/WebControl/TypeColorLine.cs index 6986f435..7c5fdbf8 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorLine.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorLine.cs @@ -1,28 +1,66 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Standardhintergrundfarben + /// The standard background colors. /// public enum TypeColorLine { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + + /// + /// Light background color. + /// Light = 8 } + /// + /// Extension methods for the enum. + /// public static class TypeColorLineExtensions { /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die Hintergrundfarbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The background color to be converted. + /// The CSS class corresponding to the background color. public static string ToClass(this TypeColorLine color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorNavbar.cs b/src/WebExpress.WebUI/WebControl/TypeColorNavbar.cs index 623f0af9..6224ed64 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorNavbar.cs @@ -1,27 +1,76 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration representing different types of navbar colors. + /// public enum TypeColorNavbar { + /// + /// Default color. + /// Default = 0, + + /// + /// Primary color. + /// Primary = 1, + + /// + /// Secondary color. + /// Secondary = 2, + + /// + /// Success color. + /// Success = 3, + + /// + /// Info color. + /// Info = 4, + + /// + /// Warning color. + /// Warning = 5, + + /// + /// Danger color. + /// Danger = 6, + + /// + /// Dark color. + /// Dark = 7, + + /// + /// Light color. + /// Light = 8, + + /// + /// White color. + /// White = 9, + + /// + /// Transparent color. + /// Transparent = 10 } + /// + /// Extension methods for the enumeration. + /// public static class TypeColorNavbarExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeColorNavbar layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorProgress.cs b/src/WebExpress.WebUI/WebControl/TypeColorProgress.cs index 0fe196d6..175f6f7d 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorProgress.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorProgress.cs @@ -1,29 +1,71 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Standardhintergrundfarben + /// The progress background colors. /// public enum TypeColorProgress { + /// + /// Default background color. + /// Default = 0, + + /// + /// Primary background color. + /// Primary = 1, + + /// + /// Secondary background color. + /// Secondary = 2, + + /// + /// Success background color. + /// Success = 3, + + /// + /// Info background color. + /// Info = 4, + + /// + /// Warning background color. + /// Warning = 5, + + /// + /// Danger background color. + /// Danger = 6, + + /// + /// Dark background color. + /// Dark = 7, + + /// + /// Light background color. + /// Light = 8, + + /// + /// White background color. + /// White = 9 } + /// + /// Extension methods for the enum. + /// public static class TypeColorProgressExtensions { /// - /// Conversion to a CSS class. + /// Converts the background color to a CSS class. /// - /// Die Hintergrundfarbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The background color to be converted. + /// The CSS class corresponding to the background color. public static string ToClass(this TypeColorProgress color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeColorText.cs b/src/WebExpress.WebUI/WebControl/TypeColorText.cs index 07d1810b..6beb3ecd 100644 --- a/src/WebExpress.WebUI/WebControl/TypeColorText.cs +++ b/src/WebExpress.WebUI/WebControl/TypeColorText.cs @@ -1,30 +1,76 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Standardtextfarben + /// The standard text colors. /// public enum TypeColorText { + /// + /// Default color. + /// Default = 0, + + /// + /// Primary color. + /// Primary = 1, + + /// + /// Secondary color. + /// Secondary = 2, + + /// + /// Success color. + /// Success = 3, + + /// + /// Info color. + /// Info = 4, + + /// + /// Warning color. + /// Warning = 5, + + /// + /// Danger color. + /// Danger = 6, + + /// + /// Dark color. + /// Dark = 7, + + /// + /// Light color. + /// Light = 8, + + /// + /// White color. + /// White = 9, + + /// + /// Muted color. + /// Muted = 11 } + /// + /// Extension methods for the enum. + /// public static class TypeColorTextExtensions { /// - /// Conversion to a CSS class. + /// Converts the color to a CSS class. /// - /// Die Farbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The color to be converted. + /// The CSS class corresponding to the color. public static string ToClass(this TypeColorText color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeDevice.cs b/src/WebExpress.WebUI/WebControl/TypeDevice.cs index 7ac95481..85238299 100644 --- a/src/WebExpress.WebUI/WebControl/TypeDevice.cs +++ b/src/WebExpress.WebUI/WebControl/TypeDevice.cs @@ -1,36 +1,36 @@ namespace WebExpress.WebUI.WebControl { /// - /// AufzÀhliung der unterstützten GerÀtetypen + /// Enumeration of supported device types /// public enum TypeDevice { /// - /// Keine Auswahl + /// No selection /// None, /// - /// Automatische Anpassung + /// Automatic adjustment /// Auto, /// - /// Für Telepfone geeignet < 576px + /// Suitable for phones < 576px /// ExtraSmall, /// - /// Für Tablets geeignet >= 576px + /// Suitable for tablets >= 576px /// Small, /// - /// Für kleine Laptops geeignet >= 768px + /// Suitable for small laptops >= 768px /// Medium, /// - /// Für Laptops & Desktops geeignet >= 992px + /// Suitable for laptops & desktops >= 992px /// Large, /// - /// Für Laptops & Desktops geeignet >= 1200px + /// Suitable for laptops & desktops >= 1200px /// ExtraLarge } diff --git a/src/WebExpress.WebUI/WebControl/TypeDirection.cs b/src/WebExpress.WebUI/WebControl/TypeDirection.cs index 8c58bc14..390e0d05 100644 --- a/src/WebExpress.WebUI/WebControl/TypeDirection.cs +++ b/src/WebExpress.WebUI/WebControl/TypeDirection.cs @@ -1,24 +1,46 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Anordnungsmâglichkeiten + /// The possible arrangements. /// public enum TypeDirection { + /// + /// The default arrangement. + /// Default, + + /// + /// The vertical arrangement. + /// Vertical, + + /// + /// The horizontal arrangement. + /// Horizontal, + + /// + /// The reverse vertical arrangement. + /// VerticalReverse, + + /// + /// The reverse horizontal arrangement. + /// HorizontalReverse } + /// + /// Extension methods for the enum. + /// public static class TypesFlexboxDirectionExtensions { /// - /// Conversion to a CSS class. + /// Converts the direction to a CSS class. /// - /// Die Anordnung, welches umgewandelt werden soll - /// Die zur Anordnung gehârende CSS-KLasse + /// The direction to be converted. + /// The CSS class corresponding to the direction. public static string ToClass(this TypeDirection direction) { return direction switch diff --git a/src/WebExpress.WebUI/WebControl/TypeDismissibleAlert.cs b/src/WebExpress.WebUI/WebControl/TypeDismissibleAlert.cs index 36506126..3d4722b2 100644 --- a/src/WebExpress.WebUI/WebControl/TypeDismissibleAlert.cs +++ b/src/WebExpress.WebUI/WebControl/TypeDismissibleAlert.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of dismissible alert. + /// public enum TypeDismissibleAlert { + /// + /// No dismissible alert. + /// None, + + /// + /// Dismissible alert. + /// Dismissible } + /// + /// Provides extension methods for the enum. + /// public static class TypeDismissibleAlertExtensions { /// - /// Conversion to a CSS class. + /// Converts the to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeDismissibleAlert layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeExpandTree.cs b/src/WebExpress.WebUI/WebControl/TypeExpandTree.cs index 61e86ca3..19900cb9 100644 --- a/src/WebExpress.WebUI/WebControl/TypeExpandTree.cs +++ b/src/WebExpress.WebUI/WebControl/TypeExpandTree.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the expansion state of a tree node. + /// public enum TypeExpandTree { + /// + /// No expansion state. + /// None, + + /// + /// The tree node is visible. + /// Visible, + + /// + /// The tree node is collapsed. + /// Collapse } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeExpandTreeExtensions { /// - /// Conversion to a CSS class. + /// Converts the expansion state to a CSS class. /// - /// Der Expansionszustand - /// Die zum Icon gehârende CSS-KLasse + /// The expansion state. + /// The CSS class corresponding to the expansion state. public static string ToClass(this TypeExpandTree expand) { return expand switch diff --git a/src/WebExpress.WebUI/WebControl/TypeFade.cs b/src/WebExpress.WebUI/WebControl/TypeFade.cs index a88d59f6..68d73acd 100644 --- a/src/WebExpress.WebUI/WebControl/TypeFade.cs +++ b/src/WebExpress.WebUI/WebControl/TypeFade.cs @@ -1,20 +1,41 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of fade effect. + /// public enum TypeFade { + /// + /// No fade effect. + /// None, + + /// + /// Fade in effect. + /// FadeIn, + + /// + /// Fade out effect. + /// FadeOut, + + /// + /// Fade show effect. + /// FadeShow, } + /// + /// Provides extension methods for the enum. + /// public static class TypeFadeExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeFade layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeFillChart.cs b/src/WebExpress.WebUI/WebControl/TypeFillChart.cs index 00b2c26e..c79992a2 100644 --- a/src/WebExpress.WebUI/WebControl/TypeFillChart.cs +++ b/src/WebExpress.WebUI/WebControl/TypeFillChart.cs @@ -1,20 +1,41 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration representing the type of fill for a chart. + /// public enum TypeFillChart { + /// + /// No fill. + /// None = 0, + + /// + /// Fill from the origin. + /// Origin = 1, + + /// + /// Fill from the start. + /// Start = 2, + + /// + /// Fill to the end. + /// End = 3 } + /// + /// Extension methods for the enumeration. + /// public static class TypeFillChartExtensions { /// - /// Conversion to a CSS class. + /// Converts the TypeFillChart value to a corresponding CSS class. /// - /// Die Farbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The TypeFillChart value to convert. + /// The CSS class corresponding to the TypeFillChart value. public static string ToType(this TypeFillChart color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeFixed.cs b/src/WebExpress.WebUI/WebControl/TypeFixed.cs index 970106a1..6efcb803 100644 --- a/src/WebExpress.WebUI/WebControl/TypeFixed.cs +++ b/src/WebExpress.WebUI/WebControl/TypeFixed.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the fixed position types for a web control. + /// public enum TypeFixed { + /// + /// No fixed position. + /// None, + + /// + /// Fixed position at the top. + /// Top, + + /// + /// Fixed position at the bottom. + /// Bottom } + /// + /// Provides extension methods for the enum. + /// public static class TypeFixedExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// A string representing the CSS class corresponding to the value. public static string ToClass(this TypeFixed layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeFormatProgress.cs b/src/WebExpress.WebUI/WebControl/TypeFormatProgress.cs index 78b25bbf..dbddd6ea 100644 --- a/src/WebExpress.WebUI/WebControl/TypeFormatProgress.cs +++ b/src/WebExpress.WebUI/WebControl/TypeFormatProgress.cs @@ -1,23 +1,41 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die ProgressBar Formate + /// The formats for the progress bar. /// public enum TypeFormatProgress { + /// + /// The default format. + /// Default, + + /// + /// The colored format. + /// Colored, + + /// + /// The striped format. + /// Striped, + + /// + /// The animated format. + /// Animated } + /// + /// Extension methods for the enum. + /// public static class TypesProgressBarFormatExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeFormatProgress layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeFormatText.cs b/src/WebExpress.WebUI/WebControl/TypeFormatText.cs index 218dde2a..eb91f7c0 100644 --- a/src/WebExpress.WebUI/WebControl/TypeFormatText.cs +++ b/src/WebExpress.WebUI/WebControl/TypeFormatText.cs @@ -1,128 +1,163 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Textformate + /// The text formats /// public enum TypeFormatText { + /// + /// The default text format. + /// Default, + /// - /// Markiert den Inhalt als Absatz. + /// Marks the content as a paragraph. /// Paragraph, + /// - /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise kursiv dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies kann beispielsweise eine taxonomische Bezeichnung, ein technischer Begriff, ein idiomatischer Ausdruck, ein Gedanke oder der Name eines Schiffes sein. + /// Represents a section of text that is set off from the rest of the content and typically displayed in italic type, without conveying any special importance or emphasis. This could be a taxonomic designation, a technical term, an idiomatic expression, a thought, or the name of a ship. /// Italic, + /// - /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise fettgedruckt dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies kann beispielsweise ein Schlüsselwort oder ein Produktname in einer Produktbewertung sein. + /// Represents a section of text that is set off from the rest of the content and typically displayed in bold type, without conveying any special importance or emphasis. This could be a keyword or product name in a product review. /// Bold, + /// - /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise unterstrichen dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies kânnte beispielsweise ein Eigenname auf in chinesischer Sprache sein oder ein Textabschnitt, der hÀufig falsch buchstabiert wird. + /// Represents a section of text that is set off from the rest of the content and typically displayed with an underline, without conveying any special importance or emphasis. This could be a proper name in Chinese or a section of text that is often misspelled. /// Underline, + /// - /// Wird für Inhalte verwendet, dienicht lÀnger relevant oder akkurat sind. Wird meist durchgestrichen dargestellt. + /// Used for content that is no longer accurate or relevant. Typically displayed with a strikethrough. /// StruckOut, + /// - /// Markiert den Titel eines Werks. + /// Marks the title of a work. /// Cite, + /// - /// Markiert eine Überschrift der obersten Ebene + /// Marks a top-level heading. /// H1, + /// - /// Markiert eine Überschrift der zweiten Ebene + /// Marks a second-level heading. /// H2, + /// - /// Markiert eine Überschrift der dritten Ebene + /// Marks a third-level heading. /// H3, + /// - /// Markiert eine Überschrift der vierten Ebene + /// Marks a fourth-level heading. /// H4, + /// - /// Markiert eine Überschrift der fünften Ebene + /// Marks a fifth-level heading. /// H5, + /// - /// Markiert eine Überschrift der untersten Ebene + /// Marks a sixth-level heading. /// H6, + /// - /// Markiert einen allgemeinen Textabschnitt. + /// Marks a general section of text. /// Span, + /// - /// Steht für das "Kleingedruckte" eines Dokuments, wie Ausschlussklauseln, Copyright-Hinweise oder andere Dinge, die für das VerstÀndnis des Dokuments nicht unbedingt nâtig sind. + /// Represents the "fine print" of a document, such as disclaimers, copyright notices, or other things that are not essential to understanding the document. /// Small, + /// - /// Markiert einen besonders wichtigen (stark hervorgehobenen) Text. + /// Marks a particularly important (strongly emphasized) text. /// Strong, + + /// + /// Centers the text. + /// Center, + /// - /// Markiert ein Programmiercode. + /// Marks a piece of programming code. /// Code, + /// - /// Markiert die Ausgabe eines Programms oder eines Computers. + /// Marks the output of a program or computer. /// Output, + /// - /// Markiert einen Wert, der Datum und Uhrzeit angibt + /// Marks a value that specifies a date and time. /// Time, + /// - /// Markiert einen tiefgestellten Text. + /// Marks subscript text. /// Sub, + /// - /// Markiert einen hochgestellten Text. + /// Marks superscript text. /// Sup, + /// - /// Steht für Text, der aus Referenzgründen hervorgehoben wird, d.h. der in anderem Kontext von Bedeutung ist. + /// Represents text that is highlighted for reference purposes, i.e., text that is relevant in another context. /// Mark, + /// - /// Markiert einen hervorgehobenen Text. + /// Marks highlighted text. /// Highlight, + /// - /// Steht für einen Begriff, dessen Definition im nÀchstgelegenen Nachkommen-Element enthalten ist. + /// Represents a term whose definition is contained in the nearest ancestor element. /// Definition, + /// - /// Markiert eine Abkürzung oder ein Akronym. + /// Marks an abbreviation or acronym. /// Abbreviation, + /// - /// Markiert eine Benutzereingabe. + /// Marks user input. /// Input, + /// - /// Markiert ein Zitat. + /// Marks a quotation. /// Blockquote, + /// - /// Markiert die Beschriftung einer Abbildung. + /// Marks the caption of a figure. /// Figcaption, + /// - /// Markiert den Inhalt dieses Elements als vorformatiert und das dieses Format erhalten bleiben soll. + /// Marks content as preformatted, meaning that the formatting should be preserved. /// Preformatted, + /// - /// Markiert den Text als Markdown, welcher in HTML umgewandelt wird + /// Marks text as Markdown, which is converted to HTML. /// Markdown - } } diff --git a/src/WebExpress.WebUI/WebControl/TypeHeight.cs b/src/WebExpress.WebUI/WebControl/TypeHeight.cs index 7368b78e..00e2bb6c 100644 --- a/src/WebExpress.WebUI/WebControl/TypeHeight.cs +++ b/src/WebExpress.WebUI/WebControl/TypeHeight.cs @@ -1,27 +1,49 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Hâhenoptionen + /// The height options. /// public enum TypeHeight { + /// + /// Default height. + /// Default, + + /// + /// Height of 25%. + /// TwentyFive, + + /// + /// Height of 50%. + /// Fifty, + + /// + /// Height of 75%. + /// SeventyFive, + + /// + /// Height of 100%. + /// OneHundred } + /// + /// Extension methods for the enum. + /// public static class TypesHeightExtensions { /// - /// Conversion to a CSS class. + /// Converts the height option to a CSS class. /// - /// Die Weite, welche umgewandelt werden soll - /// Die zur Anordnung gehârende CSS-KLasse - public static string ToClass(this TypeHeight width) + /// The height option to convert. + /// The corresponding CSS class for the height option. + public static string ToClass(this TypeHeight height) { - return width switch + return height switch { TypeHeight.TwentyFive => "h-25", TypeHeight.Fifty => "h-50", diff --git a/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignment.cs b/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignment.cs index 9ed5ba6f..e18f49d0 100644 --- a/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignment.cs +++ b/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignment.cs @@ -1,22 +1,36 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die horizontale Anordnung + /// Specifies the horizontal alignment. /// public enum TypeHorizontalAlignment { + /// + /// The default alignment. + /// Default, + + /// + /// Align to the left. + /// Left, + + /// + /// Align to the right. + /// Right } + /// + /// Provides extension methods for the enum. + /// public static class TypesHorizontalAlignmentExtensions { /// - /// Conversion to a CSS class. + /// Converts the horizontal alignment to a CSS class. /// - /// Die Ausrichtung, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The alignment to be converted. + /// The CSS class corresponding to the alignment. public static string ToClass(this TypeHorizontalAlignment alignment) { return alignment switch diff --git a/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignmentTab.cs b/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignmentTab.cs index 1d22d3e5..0dcdfb51 100644 --- a/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignmentTab.cs +++ b/src/WebExpress.WebUI/WebControl/TypeHorizontalAlignmentTab.cs @@ -1,23 +1,41 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die horizontale Anordnung + /// Specifies the horizontal alignment. /// public enum TypeHorizontalAlignmentTab { + /// + /// Default alignment. + /// Default, + + /// + /// Align to the left. + /// Left, + + /// + /// Align to the center. + /// Center, + + /// + /// Align to the right. + /// Right } + /// + /// Provides extension methods for the enum. + /// public static class TypeHorizontalAlignmentTabExtensions { /// - /// Conversion to a CSS class. + /// Converts the alignment to a CSS class. /// - /// Die Ausrichtung, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The alignment to be converted. + /// The CSS class corresponding to the alignment. public static string ToClass(this TypeHorizontalAlignmentTab alignment) { return alignment switch diff --git a/src/WebExpress.WebUI/WebControl/TypeIcon.cs b/src/WebExpress.WebUI/WebControl/TypeIcon.cs index 499971b8..16832fab 100644 --- a/src/WebExpress.WebUI/WebControl/TypeIcon.cs +++ b/src/WebExpress.WebUI/WebControl/TypeIcon.cs @@ -1,5 +1,8 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration of different types of icons. + /// public enum TypeIcon { None, @@ -112,15 +115,15 @@ public enum TypeIcon } /// - /// Erweiterung des Types + /// Provides extension methods for the enumeration. /// public static class TypeIconExtensions { /// - /// Conversion to a CSS class. + /// Converts the specified to its corresponding CSS class string. /// - /// Das Icon, welches umgewandelt werden soll - /// Die zum Icon gehârende CSS-KLasse + /// The icon to convert. + /// The CSS class string corresponding to the specified icon. public static string ToClass(this TypeIcon icon) { return icon switch diff --git a/src/WebExpress.WebUI/WebControl/TypeJustifiedFlexbox.cs b/src/WebExpress.WebUI/WebControl/TypeJustifiedFlexbox.cs index 13222ee3..9892e95c 100644 --- a/src/WebExpress.WebUI/WebControl/TypeJustifiedFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/TypeJustifiedFlexbox.cs @@ -1,22 +1,51 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of justification for a flexbox layout. + /// public enum TypeJustifiedFlexbox { + /// + /// No justification. + /// None, + + /// + /// Items are justified at the start of the container. + /// Start, + + /// + /// Items are justified at the end of the container. + /// End, + + /// + /// Items are justified at the center of the container. + /// Center, + + /// + /// Items are justified with space between them. + /// Between, + + /// + /// Items are justified with space around them. + /// Around } + /// + /// Provides extension methods for the enum. + /// public static class TypeTypeJustifiedFlexboxExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeJustifiedFlexbox layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeJustifiedTab.cs b/src/WebExpress.WebUI/WebControl/TypeJustifiedTab.cs index bbadaefb..f032a7f3 100644 --- a/src/WebExpress.WebUI/WebControl/TypeJustifiedTab.cs +++ b/src/WebExpress.WebUI/WebControl/TypeJustifiedTab.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of justified tab. + /// public enum TypeJustifiedTab { + /// + /// The default tab type. + /// Default, + + /// + /// The justified tab type. + /// Justified } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeJustifiedTabExtensions { /// - /// Conversion to a CSS class. + /// Converts the to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeJustifiedTab layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutFlexbox.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutFlexbox.cs index e8370eb8..5ba19e29 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutFlexbox.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of layout for a flexbox. + /// public enum TypeLayoutFlexbox { + /// + /// No layout specified. + /// None, + + /// + /// Default flexbox layout. + /// Default, + + /// + /// Inline flexbox layout. + /// Inline } + /// + /// Provides extension methods for the enum. + /// public static class TypeInlineFlexboxExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout type to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeLayoutFlexbox layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs index 39a41820..a7394218 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutForm.cs @@ -1,11 +1,18 @@ namespace WebExpress.WebUI.WebControl { /// - /// The layout options of the form in relation to the elements. + /// Specifies the layout options of the form in relation to the elements. /// public enum TypeLayoutForm { + /// + /// The default layout of the form. + /// Default, + + /// + /// The inline layout of the form. + /// Inline } } diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs index 1b1d569d..a890bd40 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutFormItem.cs @@ -1,12 +1,23 @@ namespace WebExpress.WebUI.WebControl { /// - /// The layout options of the items in a form. + /// Specifies the layout options for items in a form. /// public enum TypeLayoutFormItem { + /// + /// Items are arranged vertically. + /// Vertical, + + /// + /// Items are arranged horizontally. + /// Horizontal, + + /// + /// Items are arranged in a mix of vertical and horizontal layouts. + /// Mix } } diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutList.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutList.cs index a629ee09..c5a2fc54 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutList.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutList.cs @@ -1,21 +1,46 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the different types of layout lists. + /// public enum TypeLayoutList { + /// + /// The default layout. + /// Default, + + /// + /// A simple, unstyled layout. + /// Simple, + + /// + /// A grouped layout. + /// Group, + + /// + /// A flush layout with no borders. + /// Flush, + + /// + /// A horizontal layout. + /// Horizontal } + /// + /// Provides extension methods for the enum. + /// public static class TypeLayoutListExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeLayoutList layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutTab.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutTab.cs index 7c6bf224..11040e01 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutTab.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutTab.cs @@ -1,23 +1,41 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Layoutmâglichkeiten des Tabulator-Steuerelementes + /// The layout options for the tab control element. /// public enum TypeLayoutTab { + /// + /// The default layout. + /// Default, + + /// + /// The menu layout. + /// Menu, + + /// + /// The tab layout. + /// Tab, + + /// + /// The pill layout. + /// Pill } + /// + /// Extension methods for the enum. + /// public static class TypeLayoutTabExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeLayoutTab layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs index 3ae7571b..7967eb95 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutTree.cs @@ -5,12 +5,39 @@ /// public enum TypeLayoutTree { + /// + /// The default layout tree. + /// Default, + + /// + /// A flat layout tree with no nested structure. + /// Flat, + + /// + /// A simple layout tree with minimal styling. + /// Simple, + + /// + /// A grouped layout tree. + /// Group, + + /// + /// A flush layout tree with no borders between items. + /// Flush, + + /// + /// A horizontal layout tree with items displayed in a row. + /// Horizontal, + + /// + /// A tree view layout tree with expandable nodes. + /// TreeView } @@ -20,10 +47,10 @@ public enum TypeLayoutTree public static class TypeLayoutTreeExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout type to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout type to be converted. + /// The CSS class corresponding to the layout type. public static string ToClass(this TypeLayoutTree layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeLayoutTreeItem.cs b/src/WebExpress.WebUI/WebControl/TypeLayoutTreeItem.cs index 9921547e..2c5efcbe 100644 --- a/src/WebExpress.WebUI/WebControl/TypeLayoutTreeItem.cs +++ b/src/WebExpress.WebUI/WebControl/TypeLayoutTreeItem.cs @@ -1,23 +1,56 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the different types of layout for a tree item. + /// public enum TypeLayoutTreeItem { + /// + /// The default layout. + /// Default, + + /// + /// A flat, unstyled layout. + /// Flat, + + /// + /// A simple layout. + /// Simple, + + /// + /// A grouped layout. + /// Group, + + /// + /// A flush layout. + /// Flush, + + /// + /// A horizontal layout. + /// Horizontal, + + /// + /// A tree view layout. + /// TreeView } + /// + /// Provides extension methods for the enum. + /// public static class TypeLayoutTreeItemExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeLayoutTreeItem layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeModal.cs b/src/WebExpress.WebUI/WebControl/TypeModal.cs index c213c87e..42f93b40 100644 --- a/src/WebExpress.WebUI/WebControl/TypeModal.cs +++ b/src/WebExpress.WebUI/WebControl/TypeModal.cs @@ -1,13 +1,28 @@ namespace WebExpress.WebUI.WebControl { /// - /// The type of the modal. + /// Specifies the type of the modal. /// public enum TypeModal { + /// + /// No modal type specified. + /// None, + + /// + /// Modal type for forms. + /// Form, + + /// + /// Modal type for browsers. + /// Brwoser, + + /// + /// General modal type. + /// Modal } } diff --git a/src/WebExpress.WebUI/WebControl/TypeModalSize.cs b/src/WebExpress.WebUI/WebControl/TypeModalSize.cs index 5ff54b81..fc675988 100644 --- a/src/WebExpress.WebUI/WebControl/TypeModalSize.cs +++ b/src/WebExpress.WebUI/WebControl/TypeModalSize.cs @@ -1,11 +1,33 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the size of a modal dialog. + /// public enum TypeModalSize { + /// + /// The default modal size. + /// Default, + + /// + /// A small modal size. + /// Small, + + /// + /// A large modal size. + /// Large, + + /// + /// An extra large modal size. + /// ExtraLarge, + + /// + /// A fullscreen modal size. + /// Fullscreen } } diff --git a/src/WebExpress.WebUI/WebControl/TypeOnChange.cs b/src/WebExpress.WebUI/WebControl/TypeOnChange.cs index aa3f7429..1f81ff7f 100644 --- a/src/WebExpress.WebUI/WebControl/TypeOnChange.cs +++ b/src/WebExpress.WebUI/WebControl/TypeOnChange.cs @@ -1,19 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of action to take on change. + /// public enum TypeOnChange { + /// + /// No action. + /// None, + + /// + /// Submit the form. + /// Submit } - + /// + /// Provides extension methods for the enumeration. + /// public static class TypeOnChangeExtensions { /// - /// Conversion to string. + /// Converts the TypeOnChange value to its corresponding string representation. /// - /// The value. - /// Der String + /// The TypeOnChange value. + /// A string representing the action to take on change. public static string ToValue(this TypeOnChange value) { return value switch diff --git a/src/WebExpress.WebUI/WebControl/TypeOrientationSplit.cs b/src/WebExpress.WebUI/WebControl/TypeOrientationSplit.cs index 5cba0712..dc281c2a 100644 --- a/src/WebExpress.WebUI/WebControl/TypeOrientationSplit.cs +++ b/src/WebExpress.WebUI/WebControl/TypeOrientationSplit.cs @@ -1,25 +1,38 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the orientation of a split layout. + /// public enum TypeOrientationSplit { + /// + /// The layout is split horizontally. + /// Horizontal, + + /// + /// The layout is split vertically. + /// Vertical } - //public static class TypeOrientationSplitExtensions - //{ - // /// - // /// Conversion to a CSS class. - // /// - // /// The layout to be converted - // /// The CSS class belonging to the layout - // public static string ToClass(this TypeOrientationTab layout) - // { - // return layout switch - // { - // TypeOrientationTab.Vertical => "flex-column", - // _ => string.Empty, - // }; - // } - //} + /// + /// Provides extension methods for the enumeration. + /// + public static class TypeOrientationSplitExtensions + { + /// + /// Converts the value to a corresponding CSS class. + /// + /// The layout to be converted. + /// The CSS class corresponding to the layout. + public static string ToClass(this TypeOrientationSplit layout) + { + return layout switch + { + TypeOrientationSplit.Vertical => "flex-column", + _ => string.Empty, + }; + } + } } diff --git a/src/WebExpress.WebUI/WebControl/TypeOrientationTab.cs b/src/WebExpress.WebUI/WebControl/TypeOrientationTab.cs index 5bbf9688..b13f6405 100644 --- a/src/WebExpress.WebUI/WebControl/TypeOrientationTab.cs +++ b/src/WebExpress.WebUI/WebControl/TypeOrientationTab.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the orientation of a tab. + /// public enum TypeOrientationTab { + /// + /// The default orientation. + /// Default, + + /// + /// The horizontal orientation. + /// Horizontal, + + /// + /// The vertical orientation. + /// Vertical } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeOrientationTabExtensions { /// - /// Conversion to a CSS class. + /// Converts the specified layout to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeOrientationTab layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeOrientationToolBar.cs b/src/WebExpress.WebUI/WebControl/TypeOrientationToolBar.cs index 0df71556..3b4d0703 100644 --- a/src/WebExpress.WebUI/WebControl/TypeOrientationToolBar.cs +++ b/src/WebExpress.WebUI/WebControl/TypeOrientationToolBar.cs @@ -1,19 +1,36 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the orientation of the toolbar. + /// public enum TypeOrientationToolBar { + /// + /// The default orientation. + /// Default, + + /// + /// The horizontal orientation. + /// Horizontal, + + /// + /// The vertical orientation. + /// Vertical } + /// + /// Provides extension methods for the enum. + /// public static class TypeOrientationToolBarExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypeOrientationToolBar layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypePanelContainer.cs b/src/WebExpress.WebUI/WebControl/TypePanelContainer.cs index 74c766f4..fd3a22d4 100644 --- a/src/WebExpress.WebUI/WebControl/TypePanelContainer.cs +++ b/src/WebExpress.WebUI/WebControl/TypePanelContainer.cs @@ -5,18 +5,32 @@ /// public enum TypePanelContainer { + /// + /// No specific layout. + /// None, + + /// + /// Default layout with fixed width. + /// Default, + + /// + /// Fluid layout with full width. + /// Fluid } + /// + /// Extension methods for the enum. + /// public static class TypePanelFluidExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypePanelContainer layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypePanelGridRow.cs b/src/WebExpress.WebUI/WebControl/TypePanelGridRow.cs index 5f4d2ca9..52a9bd89 100644 --- a/src/WebExpress.WebUI/WebControl/TypePanelGridRow.cs +++ b/src/WebExpress.WebUI/WebControl/TypePanelGridRow.cs @@ -1,22 +1,36 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Layoutmâglichkeiten des Grid-Systems + /// The layout options for the grid system. /// public enum TypePanelGridRow { + /// + /// No specific layout. + /// None, + + /// + /// Automatic layout. + /// Auto, + + /// + /// Fluid layout. + /// Fluid } + /// + /// Extension methods for the enum. + /// public static class TypePanelGridRowExtensions { /// - /// Conversion to a CSS class. + /// Converts the layout to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypePanelGridRow layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypePillBadge.cs b/src/WebExpress.WebUI/WebControl/TypePillBadge.cs index ace291a3..127e1ef2 100644 --- a/src/WebExpress.WebUI/WebControl/TypePillBadge.cs +++ b/src/WebExpress.WebUI/WebControl/TypePillBadge.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the type of a pill badge. + /// public enum TypePillBadge { + /// + /// No badge. + /// None, + + /// + /// Pill badge. + /// Pill } + /// + /// Provides extension methods for the enum. + /// public static class TypePillBadgeExtensions { /// - /// Conversion to a CSS class. + /// Converts the to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The layout to be converted. + /// The CSS class corresponding to the layout. public static string ToClass(this TypePillBadge layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypePointChart.cs b/src/WebExpress.WebUI/WebControl/TypePointChart.cs index 9206b62b..21b49fe4 100644 --- a/src/WebExpress.WebUI/WebControl/TypePointChart.cs +++ b/src/WebExpress.WebUI/WebControl/TypePointChart.cs @@ -1,21 +1,46 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Enumeration for different types of point charts. + /// public enum TypePointChart { + /// + /// Circle type point chart. + /// Circle = 0, + + /// + /// Triangle type point chart. + /// Triangle = 1, + + /// + /// Rectangle type point chart. + /// Rect = 2, + + /// + /// Rounded rectangle type point chart. + /// RectRounded = 3, + + /// + /// Rhombus type point chart. + /// Rhombus } + /// + /// Extension methods for the enumeration. + /// public static class TypePointChartExtensions { /// - /// Conversion to a CSS class. + /// Converts the TypePointChart value to a corresponding CSS class. /// - /// Die Farbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The TypePointChart value to be converted. + /// The CSS class corresponding to the TypePointChart value. public static string ToType(this TypePointChart color) { return color switch diff --git a/src/WebExpress.WebUI/WebControl/TypeSizeButton.cs b/src/WebExpress.WebUI/WebControl/TypeSizeButton.cs index 5c66772b..dd5bf96c 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSizeButton.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSizeButton.cs @@ -1,22 +1,36 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Grâßenmâglichkeiten + /// The size options for buttons. /// public enum TypeSizeButton { + /// + /// The default size. + /// Default, + + /// + /// The small size. + /// Small, + + /// + /// The large size. + /// Large } + /// + /// Provides extension methods for the enum. + /// public static class TypeSizeButtonExtensions { /// - /// Conversion to a CSS class. + /// Converts the button size to a CSS class. /// - /// Die Grâße, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The size to be converted. + /// The CSS class corresponding to the size. public static string ToClass(this TypeSizeButton size) { return size switch diff --git a/src/WebExpress.WebUI/WebControl/TypeSizePagination.cs b/src/WebExpress.WebUI/WebControl/TypeSizePagination.cs index 28a72a95..34c47b2b 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSizePagination.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSizePagination.cs @@ -1,22 +1,36 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Grâßenmâglichkeiten + /// The size options for pagination. /// public enum TypeSizePagination { + /// + /// The default size. + /// Default, + + /// + /// The small size. + /// Small, + + /// + /// The large size. + /// Large } + /// + /// Extension methods for the enum. + /// public static class TypeSizePaginationExtensions { /// - /// Conversion to a CSS class. + /// Converts the size to a corresponding CSS class. /// - /// Die Grâße, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The size to be converted. + /// The CSS class corresponding to the size. public static string ToClass(this TypeSizePagination size) { return size switch diff --git a/src/WebExpress.WebUI/WebControl/TypeSizeProgress.cs b/src/WebExpress.WebUI/WebControl/TypeSizeProgress.cs index b1c951b8..586b1991 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSizeProgress.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSizeProgress.cs @@ -1,34 +1,56 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Grâßenmâglichkeiten + /// The size options for progress elements. /// public enum TypeSizeProgress { + /// + /// Default size. + /// Default = 0, + + /// + /// Extra small size. + /// ExtraSmall = 1, + + /// + /// Small size. + /// Small = 2, + + /// + /// Large size. + /// Large = 3, + + /// + /// Extra large size. + /// ExtraLarge = 4 } + /// + /// Extension methods for the enum. + /// public static class TypesSizeProgressExtensions { /// - /// Conversion to a CSS class. + /// Converts the size to a CSS class. /// - /// Die Grâße, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The size to be converted. + /// The CSS class corresponding to the size. public static string ToClass(this TypeSizeProgress size) { return string.Empty; } /// - /// Umwandlung in einen CSS-Style + /// Converts the size to a CSS style. /// - /// Die Grâße, welches umgewandelt werden soll - /// Der zur Grâße gehârende CSS-Style + /// The size to be converted. + /// The CSS style corresponding to the size. public static string ToStyle(this TypeSizeProgress size) { return size switch diff --git a/src/WebExpress.WebUI/WebControl/TypeSizeText.cs b/src/WebExpress.WebUI/WebControl/TypeSizeText.cs index b5e7c3f8..a8ad7c57 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSizeText.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSizeText.cs @@ -1,34 +1,56 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Grâßenmâglichkeiten + /// The size options for text. /// public enum TypeSizeText { + /// + /// Default size. + /// Default = 0, + + /// + /// Extra small size. + /// ExtraSmall = 1, + + /// + /// Small size. + /// Small = 2, + + /// + /// Large size. + /// Large = 3, + + /// + /// Extra large size. + /// ExtraLarge = 4 } + /// + /// Provides extension methods for the enum. + /// public static class TypesSizeTextExtensions { /// - /// Conversion to a CSS class. + /// Converts the size to a CSS class. /// - /// Die Grâße, welches umgewandelt werden soll - /// The CSS class belonging to the layout + /// The size to be converted. + /// The CSS class corresponding to the size. public static string ToClass(this TypeSizeText size) { return string.Empty; } /// - /// Umwandlung in einen CSS-Style + /// Converts the size to a CSS style. /// - /// Die Grâße, welches umgewandelt werden soll - /// Der zur Grâße gehârende CSS-Style + /// The size to be converted. + /// The CSS style corresponding to the size. public static string ToStyle(this TypeSizeText size) { return size switch diff --git a/src/WebExpress.WebUI/WebControl/TypeSizeUnit.cs b/src/WebExpress.WebUI/WebControl/TypeSizeUnit.cs index dbc60e43..20ce6ec4 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSizeUnit.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSizeUnit.cs @@ -1,13 +1,28 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Grâßeneinheiten + /// The size units. /// public enum TypeSizeUnit { + /// + /// Size unit in pixels. + /// Pixel = 0, + + /// + /// Size unit in percent. + /// Percent = 1, + + /// + /// Size unit in em. + /// Em = 2, + + /// + /// Size unit in rem. + /// Rem = 3 } } diff --git a/src/WebExpress.WebUI/WebControl/TypeSticky.cs b/src/WebExpress.WebUI/WebControl/TypeSticky.cs index 7d41c9e1..3866f1b9 100644 --- a/src/WebExpress.WebUI/WebControl/TypeSticky.cs +++ b/src/WebExpress.WebUI/WebControl/TypeSticky.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of sticky positioning for a web control. + /// public enum TypeSticky { + /// + /// No sticky positioning. + /// None, + + /// + /// Sticky positioning at the top. + /// Top } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeStickyExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeSticky layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeTextDecoration.cs b/src/WebExpress.WebUI/WebControl/TypeTextDecoration.cs index f40831d3..6b949aea 100644 --- a/src/WebExpress.WebUI/WebControl/TypeTextDecoration.cs +++ b/src/WebExpress.WebUI/WebControl/TypeTextDecoration.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of text decoration. + /// public enum TypeTextDecoration { + /// + /// The default text decoration. + /// Default, + + /// + /// No text decoration. + /// None } + /// + /// Provides extension methods for the enum. + /// public static class TypeTextDecorationExtensions { /// - /// Conversion to a CSS class. + /// Converts the text decoration type to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The text decoration type to be converted. + /// The CSS class corresponding to the text decoration type. public static string ToClass(this TypeTextDecoration layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeToggleDropdown.cs b/src/WebExpress.WebUI/WebControl/TypeToggleDropdown.cs index 2b2babd1..2337f31e 100644 --- a/src/WebExpress.WebUI/WebControl/TypeToggleDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/TypeToggleDropdown.cs @@ -1,18 +1,31 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of toggle dropdown. + /// public enum TypeToggleDropdown { + /// + /// No toggle dropdown. + /// None, + + /// + /// Toggle dropdown. + /// Toggle } + /// + /// Provides extension methods for the enum. + /// public static class TypeToggleDropdownExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeToggleDropdown layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypeVerticalAlignment.cs b/src/WebExpress.WebUI/WebControl/TypeVerticalAlignment.cs index 9659bc51..af4590d2 100644 --- a/src/WebExpress.WebUI/WebControl/TypeVerticalAlignment.cs +++ b/src/WebExpress.WebUI/WebControl/TypeVerticalAlignment.cs @@ -1,29 +1,59 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Ausrichtung von Inline-Elementen + /// Specifies the vertical alignment of inline elements. /// public enum TypeVerticalAlignment { + /// + /// Default alignment. + /// Default = 0, + + /// + /// Aligns with the baseline of the parent element. + /// Baseline = 1, + + /// + /// Aligns with the top of the parent element. + /// Top = 2, + + /// + /// Aligns with the middle of the parent element. + /// Middle = 3, + + /// + /// Aligns with the bottom of the parent element. + /// Bottom = 4, + + /// + /// Aligns with the top of the text. + /// TextTop = 5, + + /// + /// Aligns with the bottom of the text. + /// TextBottom = 6 } + /// + /// Provides extension methods for the enum. + /// public static class TypeVerticalAlignmentExtensions { /// - /// Conversion to a CSS class. + /// Converts the vertical alignment type to a corresponding CSS class. /// - /// Die Hintergrundfarbe, welches umgewandelt werden soll - /// The CSS class belonging to the layout - public static string ToClass(this TypeVerticalAlignment color) + /// The vertical alignment type to convert. + /// The CSS class corresponding to the vertical alignment type. + public static string ToClass(this TypeVerticalAlignment alignment) { - return color switch + return alignment switch { TypeVerticalAlignment.Baseline => "align-baseline", TypeVerticalAlignment.Top => "align-top", diff --git a/src/WebExpress.WebUI/WebControl/TypeWidth.cs b/src/WebExpress.WebUI/WebControl/TypeWidth.cs index 438a4c2b..e7d788ec 100644 --- a/src/WebExpress.WebUI/WebControl/TypeWidth.cs +++ b/src/WebExpress.WebUI/WebControl/TypeWidth.cs @@ -1,24 +1,46 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Weitenoptionen + /// Specifies the width types for a web control. /// public enum TypeWidth { + /// + /// Default width. + /// Default, + + /// + /// Twenty-five percent width. + /// TwentyFive, + + /// + /// Fifty percent width. + /// Fifty, + + /// + /// Seventy-five percent width. + /// SeventyFive, + + /// + /// One hundred percent width. + /// OneHundred } + /// + /// Extension methods for the enum. + /// public static class TypesWidthExtensions { /// - /// Conversion to a CSS class. + /// Converts the width to a CSS class. /// - /// Die Weite, welche umgewandelt werden soll - /// Die zur Anordnung gehârende CSS-KLasse + /// The width to be converted. + /// The corresponding CSS class for the width. public static string ToClass(this TypeWidth width) { return width switch diff --git a/src/WebExpress.WebUI/WebControl/TypeWrap.cs b/src/WebExpress.WebUI/WebControl/TypeWrap.cs index 0830a0ac..f50ae947 100644 --- a/src/WebExpress.WebUI/WebControl/TypeWrap.cs +++ b/src/WebExpress.WebUI/WebControl/TypeWrap.cs @@ -1,20 +1,41 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the type of wrapping for a web control. + /// public enum TypeWrap { + /// + /// No wrapping. + /// None, + + /// + /// No wrapping, content stays on a single line. + /// Nowrap, + + /// + /// Content wraps onto multiple lines. + /// Wrap, + + /// + /// Content wraps in reverse order. + /// Reverse } + /// + /// Provides extension methods for the enumeration. + /// public static class TypeWrapExtensions { /// - /// Conversion to a CSS class. + /// Converts the value to a corresponding CSS class. /// - /// The layout to be converted - /// The CSS class belonging to the layout + /// The value to be converted. + /// The CSS class corresponding to the value. public static string ToClass(this TypeWrap layout) { return layout switch diff --git a/src/WebExpress.WebUI/WebControl/TypesEditTextFormat.cs b/src/WebExpress.WebUI/WebControl/TypesEditTextFormat.cs index fa6071d6..fdabacca 100644 --- a/src/WebExpress.WebUI/WebControl/TypesEditTextFormat.cs +++ b/src/WebExpress.WebUI/WebControl/TypesEditTextFormat.cs @@ -1,12 +1,23 @@ namespace WebExpress.WebUI.WebControl { /// - /// Die Textformate + /// Specifies the text formats available for editing. /// public enum TypesEditTextFormat { + /// + /// The default text format. + /// Default, + + /// + /// A multiline text format. + /// Multiline, + + /// + /// A WYSIWYG (What You See Is What You Get) text format. + /// Wysiwyg } } diff --git a/src/WebExpress.WebUI/WebControl/TypesInputValidity.cs b/src/WebExpress.WebUI/WebControl/TypesInputValidity.cs index 16d27b25..4909edae 100644 --- a/src/WebExpress.WebUI/WebControl/TypesInputValidity.cs +++ b/src/WebExpress.WebUI/WebControl/TypesInputValidity.cs @@ -1,10 +1,28 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Represents the validity state of an input control. + /// public enum TypesInputValidity { + /// + /// The default state of the input control. + /// Default, + + /// + /// The input control is in a success state. + /// Success, + + /// + /// The input control is in a warning state. + /// Warning, + + /// + /// The input control is in an error state. + /// Error } } diff --git a/src/WebExpress.WebUI/WebControl/TypesLayoutTableRow.cs b/src/WebExpress.WebUI/WebControl/TypesLayoutTableRow.cs index aae2d4e3..f08534c1 100644 --- a/src/WebExpress.WebUI/WebControl/TypesLayoutTableRow.cs +++ b/src/WebExpress.WebUI/WebControl/TypesLayoutTableRow.cs @@ -1,15 +1,53 @@ namespace WebExpress.WebUI.WebControl { + /// + /// Specifies the different types of layout table rows. + /// public enum TypesLayoutTableRow { + /// + /// The default layout table row. + /// Default, + + /// + /// The primary layout table row. + /// Primary, + + /// + /// The secondary layout table row. + /// Secondary, + + /// + /// The success layout table row. + /// Success, + + /// + /// The info layout table row. + /// Info, + + /// + /// The warning layout table row. + /// Warning, + + /// + /// The danger layout table row. + /// Danger, + + /// + /// The light layout table row. + /// Light, + + /// + /// The dark layout table row. + /// Dark } } diff --git a/src/WebExpress.WebUI/WebControl/ValidationResult.cs b/src/WebExpress.WebUI/WebControl/ValidationResult.cs index bfb3b8ad..ec108233 100644 --- a/src/WebExpress.WebUI/WebControl/ValidationResult.cs +++ b/src/WebExpress.WebUI/WebControl/ValidationResult.cs @@ -1,28 +1,29 @@ -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents the result of a validation process. - /// - public class ValidationResult - { - /// - /// Returns the type of the validation result. - /// - public TypesInputValidity Type { get; private set; } - - /// - /// Returns the error text. - /// - public string Text { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The type of the validation result. - /// The error text. - public ValidationResult(TypesInputValidity type, string text) - { - Type = type; - Text = text; - } } -} +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents the result of a validation process. + /// + public class ValidationResult + { + /// + /// Returns the type of the validation result. + /// + public TypesInputValidity Type { get; private set; } + + /// + /// Returns the error text. + /// + public string Text { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The type of the validation result. + /// The error text. + public ValidationResult(TypesInputValidity type, string text) + { + Type = type; + Text = text; + } + } +} From 0f22c1f74df0b5c574b9426612efca472cd61136 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 28 Dec 2024 16:47:52 +0100 Subject: [PATCH 30/59] refactoring and add tests --- .../WebControl/UnitTestControlAttribute.cs | 152 ++++++++ .../WebControl/UnitTestControlAvatar.cs | 135 +++++++ .../WebControl/UnitTestControlBadge.cs | 159 ++++++++ .../WebControl/UnitTestControlCanvas.cs | 111 ++++++ .../WebControl/UnitTestControlCardCounter.cs | 183 ++++++++++ .../WebControl/UnitTestControlCarousel.cs | 115 ++++++ .../WebControl/UnitTestControlChart.cs | 267 ++++++++++++++ ...lControlHtml.cs => UnitTestControlHtml.cs} | 0 .../WebControl/UnitTestControlImage.cs | 10 +- .../WebControl/UnitTestControlLink.cs | 12 +- .../UnitTestControlMultipleProgressBar.cs | 163 +++++++++ .../WebControl/UnitTestControlProgressBar.cs | 6 +- .../WebControl/UnitTestControlTable.cs | 128 +++++++ .../WebControl/UnitTestControlText.cs | 30 ++ .../WebControl/ControlAttribute.cs | 162 ++++----- .../WebControl/ControlAvatar.cs | 161 ++++----- .../WebControl/ControlBadge.cs | 206 +++++------ .../WebControl/ControlCanvas.cs | 131 +++---- .../WebControl/ControlCardCounter.cs | 171 +++++---- .../WebControl/ControlCarousel.cs | 255 +++++++------ .../WebControl/ControlCarouselItem.cs | 57 +-- .../WebControl/ControlChart.cs | 335 ++++++++--------- .../WebControl/ControlChartDataset.cs | 77 ++-- .../WebControl/ControlMultipleProgressBar.cs | 238 ++++++------ .../ControlMultipleProgressBarItem.cs | 47 +-- .../WebControl/ControlProgressBar.cs | 2 +- .../WebControl/ControlTable.cs | 339 +++++++++--------- 27 files changed, 2506 insertions(+), 1146 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs rename src/WebExpress.WebUI.Test/WebControl/{UnitTestControlControlHtml.cs => UnitTestControlHtml.cs} (100%) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs new file mode 100644 index 00000000..7eaf0d91 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs @@ -0,0 +1,152 @@ +using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the attribute control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlAttribute + { + /// + /// Tests the id property of the attribute control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title property of the attribute control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                                                                      abc
                                                                                                                                                                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                                                                                                                                                                      WebExpress.WebUI
                                                                                                                                                                                                                                                                                      ")] + public void Name(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + Name = title, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the attribute control. + /// + [Theory] + [InlineData(TypeIcon.None, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeIcon.Star, @"
                                                                                                                                                                                                                                                                                      ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the name color property of the attribute control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                      ")] + public void NameColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + NameColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the attribute control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("value", @"
                                                                                                                                                                                                                                                                                      value
                                                                                                                                                                                                                                                                                      ")] + public void Value(string value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the attribute control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("http://example.com", @"
                                                                                                                                                                                                                                                                                      ")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + Uri = uri != null ? new Uri(uri) : null + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs new file mode 100644 index 00000000..9fd257e5 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs @@ -0,0 +1,135 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the avatar control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlAvatar + { + /// + /// Tests the id property of the avatar control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAvatar(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the user property of the avatar control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("me", @"
                                                                                                                                                                                                                                                                                      mme
                                                                                                                                                                                                                                                                                      ")] + public void User(string user, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAvatar() + { + User = user + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the image property of the avatar control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("http://example.com", @"
                                                                                                                                                                                                                                                                                      ")] + public void Image(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAvatar() + { + Image = uri != null ? new Uri(uri) : null + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the avatar control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                      ")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAvatar() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the avatar control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAvatar() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs new file mode 100644 index 00000000..2523e09d --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs @@ -0,0 +1,159 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the badge control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlBadge + { + /// + /// Tests the id property of the badge control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the badge control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData(-10, @"-10")] + [InlineData(0, @"0")] + [InlineData(10, @"10")] + public void Value(int? value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge() + { + Value = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the uri property of the badge control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("http://example.com", @"")] + public void Uri(string uri, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge() + { + Uri = uri != null ? new Uri(uri) : null + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the badge control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"")] + [InlineData(TypeColorText.Primary, @"")] + [InlineData(TypeColorText.Secondary, @"")] + [InlineData(TypeColorText.Info, @"")] + [InlineData(TypeColorText.Success, @"")] + [InlineData(TypeColorText.Warning, @"")] + [InlineData(TypeColorText.Danger, @"")] + [InlineData(TypeColorText.Light, @"")] + [InlineData(TypeColorText.Dark, @"")] + [InlineData(TypeColorText.Muted, @"")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the badge control. + /// + [Theory] + [InlineData(TypeColorBackgroundBadge.Default, @"")] + [InlineData(TypeColorBackgroundBadge.Primary, @"")] + [InlineData(TypeColorBackgroundBadge.Secondary, @"")] + [InlineData(TypeColorBackgroundBadge.Warning, @"")] + [InlineData(TypeColorBackgroundBadge.Danger, @"")] + [InlineData(TypeColorBackgroundBadge.Dark, @"")] + [InlineData(TypeColorBackgroundBadge.Light, @"")] + [InlineData(TypeColorBackgroundBadge.Transparent, @"")] + public void BackgroundColor(TypeColorBackgroundBadge backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge() + { + BackgroundColor = new PropertyColorBackgroundBadge(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the pill property of the badge control. + /// + [Theory] + [InlineData(TypePillBadge.None, @"")] + [InlineData(TypePillBadge.Pill, @"")] + public void Pill(TypePillBadge pill, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlBadge() + { + Pill = pill + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs new file mode 100644 index 00000000..ad093506 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs @@ -0,0 +1,111 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the canvas control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlCanvas + { + /// + /// Tests the id property of the canvas control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCanvas(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the canvas control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCanvas() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the width property of the canvas control. + /// + [Theory] + [InlineData(TypeWidth.Default, @"")] + [InlineData(TypeWidth.TwentyFive, @"")] + [InlineData(TypeWidth.Fifty, @"")] + [InlineData(TypeWidth.SeventyFive, @"")] + [InlineData(TypeWidth.OneHundred, @"")] + public void Width(TypeWidth width, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCanvas() + { + Width = width, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the height property of the canvas control. + /// + [Theory] + [InlineData(TypeHeight.Default, @"")] + [InlineData(TypeHeight.TwentyFive, @"")] + [InlineData(TypeHeight.Fifty, @"")] + [InlineData(TypeHeight.SeventyFive, @"")] + [InlineData(TypeHeight.OneHundred, @"")] + public void Height(TypeHeight height, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCanvas() + { + Height = height, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs new file mode 100644 index 00000000..5b3cb0fa --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs @@ -0,0 +1,183 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the card counter control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlCardCounter + { + /// + /// Tests the id property of the card counter control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"

                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the card counter control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"

                                                                                                                                                                                                                                                                                      abc
                                                                                                                                                                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"

                                                                                                                                                                                                                                                                                      WebExpress.WebUI
                                                                                                                                                                                                                                                                                      ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + Text = text, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the card counter control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData(-10, @"

                                                                                                                                                                                                                                                                                      -10

                                                                                                                                                                                                                                                                                      ")] + [InlineData(0, @"

                                                                                                                                                                                                                                                                                      0

                                                                                                                                                                                                                                                                                      ")] + [InlineData(10, @"

                                                                                                                                                                                                                                                                                      10

                                                                                                                                                                                                                                                                                      ")] + public void Value(int? value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + Value = value, + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the card counter control. + /// + [Theory] + [InlineData(null, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData(0u, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData(10u, @"

                                                                                                                                                                                                                                                                                      ")] + public void Progress(uint? value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + Progress = value + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the card counter control. + /// + [Theory] + [InlineData(TypeIcon.None, @"

                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeIcon.Star, @"

                                                                                                                                                                                                                                                                                      ")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the card counter control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"*")] + [InlineData(TypeColorText.Primary, @"*")] + [InlineData(TypeColorText.Secondary, @"*")] + [InlineData(TypeColorText.Info, @"*")] + [InlineData(TypeColorText.Success, @"*")] + [InlineData(TypeColorText.Warning, @"*")] + [InlineData(TypeColorText.Danger, @"*")] + [InlineData(TypeColorText.Light, @"*")] + [InlineData(TypeColorText.Dark, @"*")] + [InlineData(TypeColorText.Muted, @"*")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the card counter control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"*")] + [InlineData(TypeColorBackground.Primary, @"*")] + [InlineData(TypeColorBackground.Secondary, @"*")] + [InlineData(TypeColorBackground.Warning, @"*")] + [InlineData(TypeColorBackground.Danger, @"*")] + [InlineData(TypeColorBackground.Dark, @"*")] + [InlineData(TypeColorBackground.Light, @"<*/span>")] + [InlineData(TypeColorBackground.Transparent, @"*")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCardCounter() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs new file mode 100644 index 00000000..412eacfd --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs @@ -0,0 +1,115 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the carousel control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlCarousel + { + /// + /// Tests the id property of the carousel control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCarousel(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the carousel control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                      ")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCarousel() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the carousel control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlCarousel() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the carousel control. + /// + [Theory] + [InlineData(typeof(ControlText), @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlLink), @"
                                                                                                                                                                                                                                                                                      **
                                                                                                                                                                                                                                                                                      ")] + [InlineData(typeof(ControlImage), @"
                                                                                                                                                                                                                                                                                      **
                                                                                                                                                                                                                                                                                      ")] + public void Add(Type child, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var childInstance = Activator.CreateInstance(child, [null]) as IControl; + var item = new ControlCarouselItem(childInstance); + var control = new ControlCarousel(); + + // test execution + control.Add(item); + + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs new file mode 100644 index 00000000..03f90445 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs @@ -0,0 +1,267 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the chart control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlChart + { + /// + /// Tests the id property of the chart control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the chart control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                      ")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the background color property of the chart control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorBackground.Transparent, @"
                                                                                                                                                                                                                                                                                      ")] + public void BackgroundColor(TypeColorBackground backgroundColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + BackgroundColor = new PropertyColorBackground(backgroundColor) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the type property of the chart control. + /// + [Theory] + [InlineData(TypeChart.Bar, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeChart.Line, @"
                                                                                                                                                                                                                                                                                      ")] + public void Type(TypeChart type, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Type = type + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title property of the chart control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("Chart Title", @"
                                                                                                                                                                                                                                                                                      ")] + public void Title(string title, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Title = title + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title of the x-axis property of the chart control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("X-Axis Title", @"
                                                                                                                                                                                                                                                                                      ")] + public void TitleX(string titleX, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + TitleX = titleX + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the title of the y-axis property of the chart control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("Y-Axis Title", @"
                                                                                                                                                                                                                                                                                      ")] + public void TitleY(string titleY, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + TitleY = titleY + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the width property of the chart control. + /// + [Theory] + [InlineData(0, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(500, @"
                                                                                                                                                                                                                                                                                      ")] + public void Width(int width, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Width = width + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the height property of the chart control. + /// + [Theory] + [InlineData(0, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(300, @"
                                                                                                                                                                                                                                                                                      ")] + public void Height(int height, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Height = height + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the minimum property of the chart control. + /// + [Theory] + [InlineData(float.MinValue, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(0f, @"
                                                                                                                                                                                                                                                                                      ")] + public void Minimum(float minimum, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Minimum = minimum + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the maximum property of the chart control. + /// + [Theory] + [InlineData(float.MaxValue, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(100f, @"
                                                                                                                                                                                                                                                                                      ")] + public void Maximum(float maximum, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlChart() + { + Maximum = maximum + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs similarity index 100% rename from src/WebExpress.WebUI.Test/WebControl/UnitTestControlControlHtml.cs rename to src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs index b8984948..3cf7e60c 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs @@ -27,7 +27,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -50,7 +50,7 @@ public void Uri(string uri, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -73,7 +73,7 @@ public void Width(int width, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -96,7 +96,7 @@ public void Height(int height, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -120,7 +120,7 @@ public void Tooltip(string tooltip, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs index 0907f0bb..f6f186e7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs @@ -28,7 +28,7 @@ public void Id(string id, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -51,7 +51,7 @@ public void Text(string text, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -74,7 +74,7 @@ public void Uri(string uri, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -97,7 +97,7 @@ public void Title(string title, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -122,7 +122,7 @@ public void Target(TypeTarget target, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// @@ -146,7 +146,7 @@ public void Tooltip(string tooltip, string expected) // test execution var html = control.Render(context); - Assert.Equal(expected, html.Trim()); + AssertExtensions.EqualWithPlaceholders(expected, html); } /// diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs new file mode 100644 index 00000000..95952723 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs @@ -0,0 +1,163 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the multiple progress bar control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlMultipleProgressBar + { + /// + /// Tests the id property of the multiple progress bar control. + /// + [Theory] + [InlineData(null, @"0%")] + [InlineData("id", @"0%")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlMultipleProgressBar(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the format property of the multiple progress bar control. + /// + [Theory] + [InlineData(TypeFormatProgress.Default, @"0%")] + [InlineData(TypeFormatProgress.Colored, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeFormatProgress.Striped, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeFormatProgress.Animated, @"
                                                                                                                                                                                                                                                                                      ")] + public void Format(TypeFormatProgress format, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlMultipleProgressBar() + { + Format = format + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the multiple progress bar control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("abc", @"
                                                                                                                                                                                                                                                                                      abc
                                                                                                                                                                                                                                                                                      ")] + [InlineData("webexpress.webui:plugin.name", @"
                                                                                                                                                                                                                                                                                      WebExpress.WebUI
                                                                                                                                                                                                                                                                                      ")] + public void Text(string text, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var item = new ControlMultipleProgressBarItem() { Text = text }; + var control = new ControlMultipleProgressBar(null, item) + { + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the color property of the multiple progress bar control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      *
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.White, @"
                                                                                                                                                                                                                                                                                      ")] + public void Color(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var item = new ControlMultipleProgressBarItem() { Color = new PropertyColorText(color) }; + var control = new ControlMultipleProgressBar(null, item) + { + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text color property of the multiple progress bar control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.White, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                      ")] + public void TextColor(TypeColorText textColor, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlMultipleProgressBar() + { + TextColor = new PropertyColorText(textColor), + Format = TypeFormatProgress.Colored + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the value property of the form multiple progress bar control. + /// + [Theory] + [InlineData(0u, @"0%")] + [InlineData(100u, @"100%")] + public void Value(uint value, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var item = new ControlMultipleProgressBarItem() { Value = value }; + var control = new ControlMultipleProgressBar(null, item) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs index 9c30a3d1..bb33f915 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs @@ -213,9 +213,9 @@ public void Max(uint max, string expected) /// Tests the value property of the form progress bar control. ///
                                                                                                                                                                                                                                                                                      [Theory] - [InlineData(0, @"0%")] - [InlineData(100, @"100%")] - public void Value(int value, string expected) + [InlineData(0u, @"0%")] + [InlineData(100u, @"100%")] + public void Value(uint value, string expected) { // preconditions UnitTestControlFixture.CreateAndRegisterComponentHubMock(); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs new file mode 100644 index 00000000..5c498a99 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs @@ -0,0 +1,128 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the table control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlTable + { + /// + /// Tests the id property of the table control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData("id", @"
                                                                                                                                                                                                                                                                                      ")] + public void Id(string id, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTable(id) + { + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the column layout property of the table control. + /// + [Theory] + [InlineData(TypesLayoutTableRow.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypesLayoutTableRow.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + public void ColumnLayout(TypesLayoutTableRow layout, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTable + { + ColumnLayout = layout + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the responsive property of the table control. + /// + [Theory] + [InlineData(false, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(true, @"
                                                                                                                                                                                                                                                                                      ")] + public void Responsive(bool responsive, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTable + { + Responsive = responsive + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the striped property of the table control. + /// + [Theory] + [InlineData(true, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(false, @"
                                                                                                                                                                                                                                                                                      ")] + public void Striped(bool striped, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTable + { + Striped = striped + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the reflow property of the table control. + /// + [Theory] + [InlineData(true, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(false, @"
                                                                                                                                                                                                                                                                                      ")] + public void Reflow(bool reflow, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlTable + { + Reflow = reflow + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs index a939af9d..8cbaf048 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs @@ -54,5 +54,35 @@ public void Text(string text, TypeFormatText format, string expected) AssertExtensions.EqualWithPlaceholders(expected, html); } + + /// + /// Tests the text color property of the attribute control. + /// + [Theory] + [InlineData(TypeColorText.Default, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Primary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Secondary, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Info, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Success, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Warning, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Danger, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Light, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Dark, @"
                                                                                                                                                                                                                                                                                      ")] + [InlineData(TypeColorText.Muted, @"
                                                                                                                                                                                                                                                                                      ")] + public void TextColor(TypeColorText color, string expected) + { + // preconditions + UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CrerateRenderContextMock(); + var control = new ControlAttribute() + { + TextColor = new PropertyColorText(color) + }; + + // test execution + var html = control.Render(context); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs index bd8f16c6..27670a4f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs @@ -1,93 +1,93 @@ -ο»Ώ//using System; -//using System.Linq; -//using WebExpress.WebCore.Internationalization; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Display of a name-value pair. -// /// -// public class ControlAttribute : Control -// { -// /// -// /// Returns or sets the text.farbe des Namens -// /// -// public PropertyColorText NameColor { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control attribute with a name-value pair. + /// + public class ControlAttribute : Control + { + /// + /// Returns or sets the text color of the name. + /// + public PropertyColorText NameColor { get; set; } -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } -// /// -// /// Returns or sets the name. -// /// -// public string Name { get; set; } + /// + /// Returns or sets the name. + /// + public string Name { get; set; } -// /// -// /// Returns or sets the value. -// /// -// public string Value { get; set; } + /// + /// Returns or sets the value. + /// + public string Value { get; set; } -// /// -// /// Returns or sets a link. -// /// -// public Uri Uri { get; set; } + /// + /// Returns or sets a link. + /// + public Uri Uri { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlAttribute(string id = null) -// : base(id) -// { -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlAttribute(string id = null) + : base(id) + { + } -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// if (!Enable) -// { -// return null; -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + if (!Enable) + { + return null; + } -// var icon = new HtmlElementTextSemanticsSpan() -// { -// Class = Icon?.ToClass() -// }; + var icon = new HtmlElementTextSemanticsSpan() + { + Class = Icon?.ToClass() + }; -// var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Name))) -// { -// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", -// Class = NameColor?.ToClass() -// }; + var name = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Name))) + { + Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_name", + Class = NameColor?.ToClass() + }; -// var value = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(Value))) -// { -// Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_value", -// Class = NameColor?.ToClass() -// }; + var value = new HtmlElementTextSemanticsSpan(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Value))) + { + Id = string.IsNullOrWhiteSpace(Id) ? string.Empty : $"{Id}_value", + Class = NameColor?.ToClass() + }; -// var html = new HtmlElementTextContentDiv -// ( -// Icon != null && Icon.HasIcon ? icon : null, -// name, -// Uri != null ? new HtmlElementTextSemanticsA(value) { Href = Uri.ToString() } : value -// ) -// { -// Id = Id, -// Class = GetClasses(), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; + var html = new HtmlElementTextContentDiv + ( + Icon != null && Icon.HasIcon ? icon : null, + name, + Uri != null ? new HtmlElementTextSemanticsA(value) { Href = Uri.ToString() } : value + ) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs index 4f933552..f9cb8402 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs @@ -1,95 +1,90 @@ -ο»Ώ//using System; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlAvatar : Control -// { -// /// -// /// Returns or sets the avatar image. -// /// -// public Uri Image { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control that displays a user's avatar, which can include an image or initials, and optionally a modal dialog. + /// + public class ControlAvatar : Control + { + /// + /// Returns or sets the avatar image. + /// + public Uri Image { get; set; } -// /// -// /// Returns or sets the name of the user. -// /// -// public string User { get; set; } + /// + /// Returns or sets the name of the user. + /// + public string User { get; set; } -// /// -// /// Returns or sets the size. -// /// -// public TypeSizeButton Size -// { -// get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Returns or sets the size. + /// + public TypeSizeButton Size + { + get => (TypeSizeButton)GetProperty(TypeSizeButton.Default); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets a modal dialogue. -// /// -// public ControlModal Modal { get; set; } + /// + /// Returns or sets a modal dialogue. + /// + public ControlModal Modal { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlAvatar(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlAvatar(string id = null) + : base(id) + { + } -// /// -// /// Initialization -// /// -// private void Init() -// { -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var img = default(HtmlElement); -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var img = default(HtmlElement); + if (Image != null) + { + img = new HtmlElementMultimediaImg() { Src = Image.ToString(), Class = "" }; + } + else if (!string.IsNullOrWhiteSpace(User)) + { + var split = User.Split(' '); + var i = split[0].FirstOrDefault().ToString(); + i += split.Count() > 1 ? split[1].FirstOrDefault().ToString() : ""; -// if (Image != null) -// { -// img = new HtmlElementMultimediaImg() { Src = Image.ToString(), Class = "" }; -// } -// else if (!string.IsNullOrWhiteSpace(User)) -// { -// var split = User.Split(' '); -// var i = split[0].FirstOrDefault().ToString(); -// i += split.Count() > 1 ? split[1].FirstOrDefault().ToString() : ""; + img = new HtmlElementTextSemanticsB(new HtmlText(i)) + { + Class = Css.Concatenate("bg-info text-light") + }; + } -// img = new HtmlElementTextSemanticsB(new HtmlText(i)) -// { -// Class = "bg-info text-light" -// }; -// } + var html = new HtmlElementTextContentDiv(img, new HtmlText(User)) + { + Id = Id, + Class = Css.Concatenate("profile", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// var html = new HtmlElementTextContentDiv(img, new HtmlText(User)) -// { -// Id = Id, -// Class = Css.Concatenate("profile", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; + if (Modal != null) + { + html.AddUserAttribute("data-bs-toggle", "modal"); + html.AddUserAttribute("data-bs-target", "#" + Modal.Id); -// if (Modal != null) -// { -// html.AddUserAttribute("data-bs-toggle", "modal"); -// html.AddUserAttribute("data-bs-target", "#" + Modal.Id); + return new HtmlList(html, Modal.Render(renderContext)); + } -// return new HtmlList(html, Modal.Render(context)); -// } - -// return html; -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlBadge.cs b/src/WebExpress.WebUI/WebControl/ControlBadge.cs index 14cace34..960f49a4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBadge.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBadge.cs @@ -1,129 +1,95 @@ -ο»Ώ//using System; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing System; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// A numerical indicator. -// /// -// public class ControlBadge : Control -// { -// /// -// /// Returns or set the background color. -// /// -// public new PropertyColorBackgroundBadge BackgroundColor -// { -// get => (PropertyColorBackgroundBadge)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); -// } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a badge control that can display a numerical indicator. + /// + public class ControlBadge : Control + { + /// + /// Returns or set the background color. + /// + public new PropertyColorBackgroundBadge BackgroundColor + { + get => (PropertyColorBackgroundBadge)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } -// /// -// /// Return or specifies whether rounded corners should be used. -// /// -// public TypePillBadge Pill -// { -// get => (TypePillBadge)GetProperty(TypePillBadge.None); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Return or specifies whether rounded corners should be used. + /// + public TypePillBadge Pill + { + get => (TypePillBadge)GetProperty(TypePillBadge.None); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets the target uri. -// /// -// public Uri Uri { get; set; } + /// + /// Returns or sets the target uri. + /// + public Uri Uri { get; set; } -// /// -// /// Returns or sets the value. -// /// -// public string Value { get; set; } + /// + /// Returns or sets the value. + /// + public int? Value { get; set; } -// /// -// /// Return or specifies the vertical orientation.. -// /// -// public TypeVerticalAlignment VerticalAlignment -// { -// get => (TypeVerticalAlignment)GetProperty(TypeVerticalAlignment.Default); -// set => SetProperty(value, () => value.ToClass()); -// } + /// + /// Return or specifies the vertical orientation.. + /// + public TypeVerticalAlignment VerticalAlignment + { + get => (TypeVerticalAlignment)GetProperty(TypeVerticalAlignment.Default); + set => SetProperty(value, () => value.ToClass()); + } -// /// -// /// Returns or sets the size. -// /// -// public PropertySizeText Size -// { -// get => (PropertySizeText)GetPropertyObject(); -// set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); -// } + /// + /// Returns or sets the size. + /// + public PropertySizeText Size + { + get => (PropertySizeText)GetPropertyObject(); + set => SetProperty(value, () => value?.ToClass(), () => value?.ToStyle()); + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlBadge(string id = null) -// : base(id) -// { -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlBadge(string id = null) + : base(id) + { + } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The value. -// public ControlBadge(string id, string value) -// : base(id) -// { -// Value = value; + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + if (Uri != null) + { + return new HtmlElementTextSemanticsA(new HtmlText(Value.ToString())) + { + Id = Id, + Class = Css.Concatenate("badge", GetClasses()), + Style = GetStyles(), + Href = Uri.ToString(), + Role = Role + }; + } -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The value. -// public ControlBadge(string id, int value) -// : base(id) -// { -// Value = value.ToString(); - -// Init(); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// if (Uri != null) -// { -// return new HtmlElementTextSemanticsA(new HtmlText(Value.ToString())) -// { -// Id = Id, -// Class = Css.Concatenate("badge", GetClasses()), -// Style = GetStyles(), -// Href = Uri.ToString(), -// Role = Role -// }; -// } - -// return new HtmlElementTextSemanticsSpan(new HtmlText(Value.ToString())) -// { -// Id = Id, -// Class = Css.Concatenate("badge", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} + return new HtmlElementTextSemanticsSpan(new HtmlText(Value.ToString())) + { + Id = Id, + Class = Css.Concatenate("badge", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs index 2102d5f4..3436d23a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs @@ -1,91 +1,40 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlCanvas : Control -// { -// /// -// /// Returns or sets the content. -// /// -// public List Content { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlCanvas(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The content of the html element. -// public ControlCanvas(params Control[] content) -// : this() -// { -// Content.AddRange(content); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlCanvas(string id, params Control[] content) -// : this(id) -// { -// Content.AddRange(content); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlCanvas(string id, IEnumerable content) -// : this(id) -// { -// Content.AddRange(content); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id. -// /// The content of the html element. -// public ControlCanvas(string id, List content) -// : base(id) -// { -// Content = content; -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Content = new List(); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// return new HtmlElementScriptingCanvas() -// { -// Id = Id, -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; -// } -// } -//} +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a canvas control that can contain other controls. + /// + /// + /// The ControlCanvas class provides a container for other controls, allowing for the dynamic construction + /// of user interfaces. It supports adding, removing, and rendering child controls. + /// + public class ControlCanvas : Control + { + /// + /// Initializes a new instance of the class. + /// + /// The id. + public ControlCanvas(string id = null) + : base(id) + { + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementScriptingCanvas() + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs index cb91db2d..4bd96628 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs @@ -1,99 +1,96 @@ -ο»Ώ//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; +ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// InformationszΓ€hler -// /// -// public class ControlCardCounter : ControlPanelCard -// { -// /// -// /// Returns or sets the icon. -// /// -// public PropertyIcon Icon { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a counter with an icon, value, progress, and text. + /// + public class ControlCardCounter : Control + { + /// + /// Returns or sets the icon. + /// + public PropertyIcon Icon { get; set; } -// /// -// /// Returns or sets the value. des Counters -// /// -// public string Value { get; set; } + /// + /// Returns or sets the counter value. + /// + public int? Value { get; set; } -// /// -// /// Returns or sets the value of the progrss. -// /// -// public int Progress { get; set; } + /// + /// Returns or sets the value of the progrss. + /// + public uint? Progress { get; set; } -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlCardCounter(string id = null) -// : base(id) -// { -// TextColor = new PropertyColorText(TypeColorText.Default); -// Init(); -// } + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + public ControlCardCounter(string id = null) + : base(id) + { + TextColor = new PropertyColorText(TypeColorText.Default); + } -// /// -// /// Initialization -// /// -// private void Init() -// { -// Progress = -1; -// } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var html = new HtmlElementTextSemanticsSpan() + { + Id = Id, + Class = Css.Concatenate("card-counter", GetClasses()), + Style = GetStyles(), + Role = Role + }; -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// Content.Clear(); + if (Icon != null && Icon.HasIcon) + { + html.Add(new ControlIcon() + { + Icon = Icon, + TextColor = TextColor, + HorizontalAlignment = TypeHorizontalAlignment.Right + }.Render(renderContext)); + } -// if (Icon != null && Icon.HasIcon) -// { -// Content.Add(new ControlIcon() -// { -// Icon = Icon, -// TextColor = TextColor, -// HorizontalAlignment = TypeHorizontalAlignment.Right -// }); -// } + var text = new ControlText(string.IsNullOrWhiteSpace(Id) ? null : Id + "_header") + { + Text = Value.HasValue ? Value.Value.ToString() : null, + Format = TypeFormatText.H4 + }; -// var text = new ControlText(string.IsNullOrWhiteSpace(Id) ? null : Id + "_header") -// { -// Text = Value, -// Format = TypeFormatText.H4 -// }; + var info = new ControlText() + { + Text = Text, + Format = TypeFormatText.Span, + TextColor = new PropertyColorText(TypeColorText.Muted) + }; -// var info = new ControlText() -// { -// Text = Text, -// Format = TypeFormatText.Span, -// TextColor = new PropertyColorText(TypeColorText.Muted) -// }; + html.Add(new ControlPanel(null, text, info) { }.Render(renderContext)); -// Content.Add(new ControlPanel(text, info) { }); + if (Progress.HasValue) + { + html.Add(new ControlProgressBar() + { + Value = Progress.Value, + Format = TypeFormatProgress.Striped, + BackgroundColor = BackgroundColor, + //Color = Color, + Size = TypeSizeProgress.Small + }.Render(renderContext)); + } -// if (Progress > -1) -// { -// Content.Add(new ControlProgressBar() -// { -// Value = Progress, -// Format = TypeFormatProgress.Striped, -// BackgroundColor = BackgroundColor, -// //Color = Color, -// Size = TypeSizeProgress.Small -// }); -// } - -// return base.Render(context); -// } -// } -//} + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs index f7d8daf2..fe1c2704 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs @@ -1,115 +1,140 @@ -ο»Ώ//using System.Collections.Generic; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Creates a slideshow. -// /// -// public class ControlCarousel : Control -// { -// /// -// /// Returns or sets the content. -// /// -// public List Items { get; private set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlCarousel(string id = null) -// : base(string.IsNullOrWhiteSpace(id) ? "carousel" : id) -// { -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The contents of the slideshow. -// public ControlCarousel(params ControlCarouselItem[] items) -// : this() -// { -// Items.AddRange(items); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// // indicators -// var indicators = new HtmlElementTextContentUl() { Class = "carousel-indicators" }; -// var index = 0; - -// foreach (var v in Items) -// { -// var i = new HtmlElementTextContentLi() { Class = index == 0 ? "active" : string.Empty }; -// i.AddUserAttribute("data-bs-target", "#" + Id); -// i.AddUserAttribute("data-bs-slide-to", index.ToString()); - -// indicators.Elements.Add(i); - -// index++; -// } - -// index = 0; - -// // items -// var inner = new HtmlElementTextContentDiv() { Class = "carousel-inner" }; -// foreach (var v in Items) -// { -// var i = new HtmlElementTextContentDiv(v?.Control.Render(context)) { Class = index == 0 ? "carousel-item active" : "carousel-item" }; - -// if (!string.IsNullOrWhiteSpace(v.Headline) || !string.IsNullOrWhiteSpace(v.Text)) -// { -// var caption = new HtmlElementTextContentDiv -// ( -// new HtmlElementSectionH3() { Text = v.Headline }, -// new HtmlElementTextContentP() { Text = v.Text } -// ) -// { -// Class = "carousel-caption" -// }; - -// i.Elements.Add(caption); -// } - -// inner.Elements.Add(i); - -// index++; -// } - -// // navigation -// var navLeft = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-prev-icon" }) -// { -// Class = "carousel-control-prev", -// Href = "#" + Id -// }; -// navLeft.AddUserAttribute("data-bs-slide", "prev"); - -// var navRight = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-next-icon" }) -// { -// Class = "carousel-control-next", -// Href = "#" + Id -// }; -// navRight.AddUserAttribute("data-bs-slide", "next"); - -// var html = new HtmlElementTextContentDiv -// ( -// indicators, inner, navLeft, navRight -// ) -// { -// Id = Id, -// Class = Css.Concatenate("carousel slide", GetClasses()), -// Style = GetStyles() -// }; - -// html.AddUserAttribute("data-bs-ride", "carousel"); - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a carousel control that can contain multiple carousel items. + /// + public class ControlCarousel : Control + { + private readonly List _items = []; + + /// + /// Returns the collection of carousel items. + /// + /// + /// An representing the carousel items. + /// + public IEnumerable Items => _items; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The carousel items to be added. + public ControlCarousel(string id = null, params ControlCarouselItem[] items) + : base(string.IsNullOrWhiteSpace(id) ? "carousel" : id) + { + _items.AddRange(items); + } + + /// + /// Adds one or more carousel items to the carousel. + /// + /// The carousel items to be added. + public void Add(params ControlCarouselItem[] items) + { + _items.AddRange(items); + } + + /// + /// Adds one or more carousel items to the carousel. + /// + /// The carousel items to be added. + public void Add(IEnumerable items) + { + _items.AddRange(items); + } + + /// + /// Clears all carousel items from the carousel. + /// + public void Clear() + { + _items.Clear(); + } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + // indicators + var indicators = new HtmlElementTextContentUl() { Class = "carousel-indicators" }; + var index = 0; + + foreach (var v in Items) + { + var i = new HtmlElementTextContentLi() { Class = index == 0 ? "active" : string.Empty }; + i.AddUserAttribute("data-bs-target", "#" + Id); + i.AddUserAttribute("data-bs-slide-to", index.ToString()); + + indicators.Add(i); + + index++; + } + + index = 0; + + // items + var inner = new HtmlElementTextContentDiv() { Class = "carousel-inner" }; + foreach (var v in Items) + { + var i = new HtmlElementTextContentDiv(v?.Control.Render(renderContext)) + { + Class = index == 0 ? "carousel-item active" : "carousel-item" + }; + + if (!string.IsNullOrWhiteSpace(v.Headline) || !string.IsNullOrWhiteSpace(v.Text)) + { + var caption = new HtmlElementTextContentDiv + ( + new HtmlElementSectionH3() { Text = v.Headline }, + new HtmlElementTextContentP() { Text = v.Text } + ) + { + Class = "carousel-caption" + }; + + i.Add(caption); + } + + inner.Add(i); + + index++; + } + + // navigation + var navLeft = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-prev-icon" }) + { + Class = "carousel-control-prev", + Href = "#" + Id + }; + navLeft.AddUserAttribute("data-bs-slide", "prev"); + + var navRight = new HtmlElementTextSemanticsA(new HtmlElementTextSemanticsSpan() { Class = "carousel-control-next-icon" }) + { + Class = "carousel-control-next", + Href = "#" + Id + }; + navRight.AddUserAttribute("data-bs-slide", "next"); + + var html = new HtmlElementTextContentDiv + ( + indicators, inner, navLeft, navRight + ) + { + Id = Id, + Class = Css.Concatenate("carousel slide", GetClasses()), + Style = GetStyles() + }; + + html.AddUserAttribute("data-bs-ride", "carousel"); + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs index 8f50f631..ce670799 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarouselItem.cs @@ -1,31 +1,32 @@ -ο»Ώ//namespace WebExpress.WebUI.WebControl -//{ -// /// -// /// Creates a slideshow element. -// /// -// public class ControlCarouselItem -// { -// /// -// /// Returns or sets the headline. -// /// -// public string Headline { get; set; } +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Represents an slideshow element in a carousel control. + /// + public class ControlCarouselItem + { + /// + /// Returns or sets the headline. + /// + public string Headline { get; set; } -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } + /// + /// Returns or sets the text. + /// + public string Text { get; set; } -// /// -// /// Retruns or sets the slideshow element, such as an image. -// /// -// public IControl Control { get; set; } + /// + /// Retruns or sets the slideshow element, such as an image. + /// + public IControl Control { get; set; } -// /// -// /// Initializes a new instance of the class. -// /// -// public ControlCarouselItem() -// { -// } - -// } -//} + /// + /// Initializes a new instance of the class with an optional control. + /// + /// The control to be used in the carousel item. If null, no control is set. + public ControlCarouselItem(IControl control = null) + { + Control = control; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlChart.cs b/src/WebExpress.WebUI/WebControl/ControlChart.cs index fcb1159c..219796c3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChart.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChart.cs @@ -1,165 +1,170 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Globalization; -//using System.Linq; -//using System.Text; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; -//using WebExpress.WebCore.WebUri; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlChart : Control -// { -// /// -// /// Returns or sets the type. -// /// -// public TypeChart Type { get; set; } - -// /// -// /// Returns or sets the title. -// /// -// public string Title { get; set; } - -// /// -// /// Returns or sets the title of the x-axis. -// /// -// public string TitleX { get; set; } - -// /// -// /// Returns or sets the title of the y-axis. -// /// -// public string TitleY { get; set; } - -// /// -// /// Returns or sets the data. -// /// -// public ICollection Labels { get; set; } = new List(); - -// /// -// /// Returns or sets the width. -// /// -// public new int Width { get; set; } - -// /// -// /// Returns or sets the height. -// /// -// public new int Height { get; set; } - -// /// -// /// Returns or sets the minimum. -// /// -// public float Minimum { get; set; } = float.MinValue; - -// /// -// /// Returns or sets the maximum. -// /// -// public float Maximum { get; set; } = float.MaxValue; - -// /// -// /// Returns or sets the data. -// /// -// public ICollection Data { get; set; } = new List(); - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlChart(string id = null) -// : base(id) -// { -// } - -// /// -// /// Initializes the control. -// /// -// /// The context in which the control is rendered. -// public void Initialize(RenderContext context) -// { -// context.VisualTree.HeaderScriptLinks.Add(UriResource.Combine(context.PageContext?.ApplicationContext?.ContextPath, "/assets/js/Chart.min.js")); -// context.VisualTree.CssLinks.Add(UriResource.Combine(context.PageContext?.ApplicationContext?.ContextPath, "/assets/css/Chart.min.css")); - -// var builder = new StringBuilder(); -// var data = new List(); -// builder.Append($"var config_{Id} = {{"); -// //if (Type != TypeChart.Polar) -// { -// builder.Append($"type:'{Type.ToType()}',"); -// } -// builder.Append("data:{"); -// builder.Append($"labels:[{string.Join(",", Labels.Select(x => $"'{x}'"))}],"); -// builder.Append("datasets:[{"); -// foreach (var v in Data) -// { -// var buf = new StringBuilder(); - -// buf.Append($"label:'{v.Title}',"); -// buf.Append($"backgroundColor:{(v.BackgroundColor.Count <= 1 ? v.BackgroundColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BackgroundColor.Select(x => $"'{x}'"))} ]")},"); -// buf.Append($"borderColor:{(v.BorderColor.Count <= 1 ? v.BorderColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BorderColor.Select(x => $"'{x}'"))} ]")},"); -// buf.Append($"data:["); -// if (v.Data != null) -// { -// buf.Append(string.Join(",", v.Data.Select(x => x.ToString(CultureInfo.InvariantCulture)))); -// } -// buf.Append($"],"); -// if (Type == TypeChart.Line) -// { -// buf.Append($"fill:'{v.Fill.ToType()}',"); -// buf.Append($"pointStyle:'{v.Point.ToType()}'"); -// } -// data.Add(buf); -// } -// builder.Append(string.Join("},{", data)); -// builder.Append("}]"); -// builder.Append("},"); -// builder.Append("options:{"); -// builder.Append("responsive:true,"); -// builder.Append($"title:{{display:{(string.IsNullOrWhiteSpace(Title) ? "false" : "true")},text:'{Title}'}},"); -// builder.Append("tooltips:{mode:'index',intersect:false},"); -// builder.Append("hover:{mode:'nearest',intersect:true},"); -// if (Type == TypeChart.Line || Type == TypeChart.Bar) -// { -// builder.Append($"scales:{{"); -// builder.Append($"xAxes:[{{display: true,scaleLabel:{{display:true,labelString:'{TitleX}'}}}}],"); -// builder.Append($"yAxes:[{{display:true,ticks:{{{(Minimum != float.MinValue ? $"min:{Minimum},suggestedMin:{Minimum}," : "")}{(Maximum != float.MaxValue ? $"max:{Maximum},suggestedMax:{Maximum}," : "")}}},scaleLabel:{{display:true,labelString:'{TitleY}'}}}}]"); -// builder.Append($"}}"); -// } -// builder.Append("}};"); - -// builder.AppendLine($"var chart_{Id} = new Chart(document.getElementById('{Id}').getContext('2d'), config_{Id});"); - -// context.VisualTree.AddScript($"chart_{Id}", builder.ToString()); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// Initialize(context); - -// var html = new HtmlElementScriptingCanvas() -// { -// Id = Id, -// Class = Css.Concatenate("", GetClasses()), -// Style = GetStyles(), -// Role = Role -// }; - -// if (Width > 0) -// { -// html.Width = Width; -// html.Style = Css.Concatenate($"width: {Width}px;", html.Style); -// } - -// if (Height > 0) -// { -// html.Height = Height; -// html.Style = Css.Concatenate($"height: {Height}px;", html.Style); -// } - -// return new HtmlElementTextContentDiv(html) { Class = "chart-container" }; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a chart control that can be used to display various types of charts. + /// + public class ControlChart : Control + { + private readonly List _datasets = []; + + /// + /// Returns the datasets. + /// + public IEnumerable Data => _datasets; + + /// + /// Returns or sets the labels. + /// + public ICollection Labels { get; set; } = new List(); + + /// + /// Returns or sets the type. + /// + public TypeChart Type { get; set; } + + /// + /// Returns or sets the title. + /// + public string Title { get; set; } + + /// + /// Returns or sets the title of the x-axis. + /// + public string TitleX { get; set; } + + /// + /// Returns or sets the title of the y-axis. + /// + public string TitleY { get; set; } + + /// + /// Returns or sets the width. + /// + public new int Width { get; set; } + + /// + /// Returns or sets the height. + /// + public new int Height { get; set; } + + /// + /// Returns or sets the minimum. + /// + public float Minimum { get; set; } = float.MinValue; + + /// + /// Returns or sets the maximum. + /// + public float Maximum { get; set; } = float.MaxValue; + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The datasets to be used in the chart. + public ControlChart(string id = null, params ControlChartDataset[] datasets) + : base(id) + { + _datasets.AddRange(datasets); + } + /// + /// Initializes the control. + /// + /// The context in which the control is rendered. + public void Initialize(IRenderControlContext renderContext) + { + //renderContext.AddHeaderScriptLinks(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/js/Chart.min.js")); + //renderContext.AddCssLinks(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/css/Chart.min.css")); + + var builder = new StringBuilder(); + var data = new List(); + builder.Append($"var config_{Id} = {{"); + //if (Type != TypeChart.Polar) + { + builder.Append($"type:'{Type.ToType()}',"); + } + builder.Append("data:{"); + builder.Append($"labels:[{string.Join(",", Labels.Select(x => $"'{x}'"))}],"); + builder.Append("datasets:[{"); + foreach (var v in Data) + { + var buf = new StringBuilder(); + + buf.Append($"label:'{v.Title}',"); + buf.Append($"backgroundColor:{(v.BackgroundColor.Count <= 1 ? v.BackgroundColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BackgroundColor.Select(x => $"'{x}'"))} ]")},"); + buf.Append($"borderColor:{(v.BorderColor.Count <= 1 ? v.BorderColor.Select(x => $"'{x}'").FirstOrDefault()?.ToString() : $"[ {string.Join(",", v.BorderColor.Select(x => $"'{x}'"))} ]")},"); + buf.Append($"data:["); + if (v.Data != null) + { + buf.Append(string.Join(",", v.Data.Select(x => x.ToString(CultureInfo.InvariantCulture)))); + } + buf.Append($"],"); + if (Type == TypeChart.Line) + { + buf.Append($"fill:'{v.Fill.ToType()}',"); + buf.Append($"pointStyle:'{v.Point.ToType()}'"); + } + data.Add(buf); + } + builder.Append(string.Join("},{", data)); + builder.Append("}]"); + builder.Append("},"); + builder.Append("options:{"); + builder.Append("responsive:true,"); + builder.Append($"title:{{display:{(string.IsNullOrWhiteSpace(Title) ? "false" : "true")},text:'{Title}'}},"); + builder.Append("tooltips:{mode:'index',intersect:false},"); + builder.Append("hover:{mode:'nearest',intersect:true},"); + if (Type == TypeChart.Line || Type == TypeChart.Bar) + { + builder.Append($"scales:{{"); + builder.Append($"xAxes:[{{display: true,scaleLabel:{{display:true,labelString:'{TitleX}'}}}}],"); + builder.Append($"yAxes:[{{display:true,ticks:{{{(Minimum != float.MinValue ? $"min:{Minimum},suggestedMin:{Minimum}," : "")}{(Maximum != float.MaxValue ? $"max:{Maximum},suggestedMax:{Maximum}," : "")}}},scaleLabel:{{display:true,labelString:'{TitleY}'}}}}]"); + builder.Append($"}}"); + } + builder.Append("}};"); + + builder.AppendLine($"var chart_{Id} = new Chart(document.getElementById('{Id}').getContext('2d'), config_{Id});"); + + renderContext.AddScript($"chart_{Id}", builder.ToString()); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + Initialize(renderContext); + + var html = new HtmlElementScriptingCanvas() + { + Id = Id, + Class = Css.Concatenate("", GetClasses()), + Style = GetStyles(), + Role = Role + }; + + if (Width > 0) + { + html.Width = Width; + html.Style = Css.Concatenate($"width: {Width}px;", html.Style); + } + + if (Height > 0) + { + html.Height = Height; + html.Style = Css.Concatenate($"height: {Height}px;", html.Style); + } + + return new HtmlElementTextContentDiv(html) { Class = "chart-container" }; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs index f7bdc779..148b7e7e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChartDataset.cs @@ -1,44 +1,47 @@ -ο»Ώ//using System.Collections.Generic; +ο»Ώusing System.Collections.Generic; -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlChartDataset -// { -// /// -// /// Returns or sets the title. -// /// -// public string Title { get; set; } +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a dataset for a chart control. + /// + public class ControlChartDataset + { + /// + /// Returns or sets the title. + /// + public string Title { get; set; } -// /// -// /// Returns or sets the data. -// /// -// public float[] Data { get; set; } + /// + /// Returns or sets the data. + /// + public float[] Data { get; set; } -// /// -// /// Returns or sets the background color. -// /// -// public List BackgroundColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; + /// + /// Returns or sets the background color. + /// + public List BackgroundColor { get; set; } = [new PropertyColorChart(TypeColorChart.Primary)]; -// /// -// /// Returns or sets the frame color. -// /// -// public List BorderColor { get; set; } = new List { new PropertyColorChart(TypeColorChart.Primary) }; + /// + /// Returns or sets the frame color. + /// + public List BorderColor { get; set; } = [new PropertyColorChart(TypeColorChart.Primary)]; -// /// -// /// Returns or sets how the data series are populated. -// /// -// public TypeFillChart Fill { get; set; } = TypeFillChart.None; + /// + /// Returns or sets how the data series are populated. + /// + public TypeFillChart Fill { get; set; } = TypeFillChart.None; -// /// -// /// Returns or sets how the data series are populated. -// /// -// public TypePointChart Point { get; set; } = TypePointChart.Circle; + /// + /// Returns or sets how the data series are populated. + /// + public TypePointChart Point { get; set; } = TypePointChart.Circle; -// /// -// /// Initializes a new instance of the class. -// /// -// public ControlChartDataset() -// { -// } -// } -//} + /// + /// Initializes a new instance of the class. + /// + public ControlChartDataset() + { + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs index b78e31e9..00ba0201 100644 --- a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs @@ -1,126 +1,112 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlMultipleProgressBar : Control -// { -// /// -// /// Returns or sets the format of the progress bar. -// /// -// public TypeFormatProgress Format { get; set; } - -// /// -// /// Returns or sets the value. -// /// -// public List Items { get; private set; } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// public ControlMultipleProgressBar(string id = null) -// : base(id) -// { -// Init(); -// } - -// /// -// /// Initializes a new instance of the class. -// /// -// /// The id of the control. -// /// The value. -// public ControlMultipleProgressBar(string id, params ControlMultipleProgressBarItem[] items) -// : this(id) -// { -// Items.AddRange(items); -// } - -// /// -// /// Initialization -// /// -// private void Init() -// { -// Items = new List(); -// } - -// /// -// /// Convert to html. -// /// -// /// The context in which the control is rendered. -// /// The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// var barClass = new List(); - -// switch (Format) -// { -// case TypeFormatProgress.Colored: -// barClass.Add("progress-bar"); -// break; - -// case TypeFormatProgress.Striped: -// barClass.Add("progress-bar"); -// barClass.Add("progress-bar-striped"); -// break; - -// case TypeFormatProgress.Animated: -// barClass.Add("progress-bar"); -// barClass.Add("progress-bar-striped"); -// barClass.Add("progress-bar-animated"); -// break; - -// default: -// return new HtmlElementFormProgress(Items.Select(x => x.Value).Sum() + "%") -// { -// Id = Id, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role, -// Min = "0", -// Max = "100", -// Value = Items.Select(x => x.Value).Sum().ToString() -// }; -// } - -// Classes.Add("progress"); - -// var html = new HtmlElementTextContentDiv() -// { -// Id = Id, -// Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; - -// foreach (var v in Items) -// { -// var styles = new List -// { -// "width: " + v.Value + "%;" -// }; - -// var c = new List(barClass) -// { -// v.BackgroundColor.ToClass() -// }; - -// barClass.Add(v.Color.ToClass()); - -// var bar = new HtmlElementTextContentDiv(new HtmlText(v.Text)) -// { -// Id = Id, -// Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join(" ", styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; - -// html.Elements.Add(bar); -// } - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control that displays multiple progress bars. + /// + public class ControlMultipleProgressBar : Control + { + private readonly List _items = []; + + /// + /// Returns the items of the multiple progress bar. + /// + public IEnumerable Items => _items; + + /// + /// Returns or sets the format of the progress bar. + /// + public TypeFormatProgress Format { get; set; } + + /// + /// Initializes a new instance of the class with the specified id and items. + /// + /// The id of the control. + /// The items to be added to the multiple progress bar. + public ControlMultipleProgressBar(string id = null, params ControlMultipleProgressBarItem[] items) + : base(id) + { + _items.AddRange(items); + } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + var barClass = new List(); + + switch (Format) + { + case TypeFormatProgress.Colored: + barClass.Add("progress-bar"); + break; + + case TypeFormatProgress.Striped: + barClass.Add("progress-bar"); + barClass.Add("progress-bar-striped"); + break; + + case TypeFormatProgress.Animated: + barClass.Add("progress-bar"); + barClass.Add("progress-bar-striped"); + barClass.Add("progress-bar-animated"); + break; + + default: + return new HtmlElementFormProgress(_items.Select(x => (int)x.Value).Sum() + "%") + { + Id = Id, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role, + Min = "0", + Max = "100", + Value = _items.Select(x => (int)x.Value).Sum().ToString() + }; + } + + Classes.Add("progress"); + + var html = new HtmlElementTextContentDiv() + { + Id = Id, + Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + + foreach (var v in _items) + { + var styles = new List + { + "width: " + v.Value + "%;" + }; + + var c = new List(barClass) + { + v.BackgroundColor.ToClass(), + v.Color.ToClass() + }; + + var bar = new HtmlElementTextContentDiv(new HtmlText(I18N.Translate(renderContext.Request?.Culture, v.Text))) + { + Id = Id, + Class = string.Join(" ", c.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join(" ", styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + + html.Add(bar); + } + + return html; + } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs index 251516eb..796d2c05 100644 --- a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBarItem.cs @@ -1,25 +1,28 @@ -ο»Ώ//namespace WebExpress.WebUI.WebControl -//{ -// public class ControlMultipleProgressBarItem -// { -// /// -// /// Returns or sets the text.farbe -// /// -// public PropertyColorText Color { get; set; } +ο»Ώnamespace WebExpress.WebUI.WebControl +{ + /// + /// Represents an item in a multiple progress bar control. + /// + public class ControlMultipleProgressBarItem + { + /// + /// Returns or sets the text color. + /// + public PropertyColorText Color { get; set; } = new PropertyColorText(TypeColorText.Default); -// /// -// /// Returns or set the background color. -// /// -// public PropertyColorBackground BackgroundColor { get; set; } + /// + /// Returns or sets the background color. + /// + public PropertyColorBackground BackgroundColor { get; set; } = new PropertyColorBackground(TypeColorBackground.Default); -// /// -// /// Returns or sets the value. -// /// -// public int Value { get; set; } + /// + /// Returns or sets the value. + /// + public uint Value { get; set; } -// /// -// /// Returns or sets the text. -// /// -// public string Text { get; set; } -// } -//} + /// + /// Returns or sets the text. + /// + public string Text { get; set; } + } +} diff --git a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs index 25a7ab2a..6c7deefc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs @@ -36,7 +36,7 @@ public TypeSizeProgress Size /// /// Returns or sets the value. /// - public int Value { get; set; } + public uint Value { get; set; } = 0; /// /// Returns or sets the minimum value. diff --git a/src/WebExpress.WebUI/WebControl/ControlTable.cs b/src/WebExpress.WebUI/WebControl/ControlTable.cs index 1318744b..a92fc24f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTable.cs @@ -1,176 +1,163 @@ -ο»Ώ//using System.Collections.Generic; -//using System.Linq; -//using WebExpress.WebCore.WebHtml; -//using WebExpress.WebCore.WebPage; - -//namespace WebExpress.WebUI.WebControl -//{ -// / -// / Represents a table control. -// / -// public class ControlTable : Control -// { -// / -// / Returns or sets the layout. der SpaltenΓΌberschrift -// / -// public TypesLayoutTableRow ColumnLayout { get; set; } - -// / -// / Returns or sets the columns. -// / -// public List Columns { get; private set; } - -// / -// / Returns or sets the rows. -// / -// public List Rows { get; private set; } - -// / -// / Returns or sets the responsive property. -// / -// public bool Responsive { get; set; } - -// / -// / Returns or sets the striped property. -// / -// public bool Striped { get; set; } - -// / -// / Returns or sets the table to be rotated. -// / -// public bool Reflow { get; set; } - -// / -// / Initializes a new instance of the class. -// / -// / The id of the control. -// public ControlTable(string id = null) -// : base(id) -// { -// Striped = true; -// Columns = new List(); -// Rows = new List(); -// } - -// / -// / Adds a column. -// / -// / The header of the column. -// public virtual void AddColumn(string name) -// { -// Columns.Add(new ControlTableColumn(null) -// { -// Text = name -// }); -// } - -// / -// / Adds a column. -// / -// / The header of the column. -// / The icon of the column. -// public virtual void AddColumn(string name, PropertyIcon icon) -// { -// Columns.Add(new ControlTableColumn(null) -// { -// Text = name, -// Icon = icon -// }); -// } - -// / -// / Adds a column. -// / -// / The header of the column. -// / The icon of the column. -// / The layout of the column. -// public virtual void AddColumn(string name, PropertyIcon icon, TypesLayoutTableRow layout) -// { -// Columns.Add(new ControlTableColumn(null) -// { -// Text = name, -// Icon = icon, -// Layout = layout -// }); -// } - -// / -// / Adds a row. -// / -// / The cells of the row. -// public void AddRow(params Control[] cells) -// { -// var r = new ControlTableRow(null); -// r.Cells.AddRange(cells); - -// Rows.Add(r); -// } - -// / -// / Adds a row. -// / -// / The cells of the row. -// / The css class. -// public void AddRow(Control[] cells, string cssClass = null) -// { -// var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }) }; -// r.Cells.AddRange(cells); - -// Rows.Add(r); -// } - -// / -// / Adds a row. -// / -// / The cells of the row. -// / The layout. -// / The css class. -// public void AddRow(Control[] cells, TypesLayoutTableRow layout, string cssClass = null) -// { -// var r = new ControlTableRow(null) { Classes = new List(new[] { cssClass }), Layout = layout }; -// r.Cells.AddRange(cells); - -// Rows.Add(r); -// } - -// / -// / Convert to html. -// / -// / The context in which the control is rendered. -// / The control as html. -// public override IHtmlNode Render(IRenderContext context) -// { -// Columns.ForEach(x => x.Layout = ColumnLayout); -// var classes = Classes.ToList(); -// classes.Add("table"); - -// if (Striped) -// { -// classes.Add("table-striped"); -// } - -// if (Responsive) -// { -// classes.Add("table-responsive"); -// } - -// if (Reflow) -// { -// classes.Add("table-reflow"); -// } - -// var html = new HtmlElementTableTable() -// { -// Id = Id, -// Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), -// Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), -// Role = Role -// }; - -// html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(context))); -// html.Rows.AddRange(from x in Rows select x.Render(context) as HtmlElementTableTr); - -// return html; -// } -// } -//} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a table control. + /// + public class ControlTable : Control + { + private readonly List _columns = []; + private readonly List _rows = []; + + /// + /// Returns the columns of the table. + /// + public IEnumerable Columns => _columns; + + /// + /// Returns the rows of the table. + /// + public IEnumerable Rows => _rows; + + /// + /// Returns or sets the layout of the column header. + /// + public TypesLayoutTableRow ColumnLayout { get; set; } + + /// + /// Returns or sets a value indicating whether the table is responsive. + /// + public bool Responsive { get; set; } + + /// + /// Returns or sets a value indicating whether the table is striped. + /// + public bool Striped { get; set; } + + /// + /// Returns or sets a value indicating whether the table should reflow. + /// + public bool Reflow { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The columns to add to the table. + /// The rows to add to the table. + public ControlTable(string id = null, ControlTableColumn[] columns = null, params ControlTableRow[] rows) + : base(id) + { + Striped = true; + _columns.AddRange(columns ?? []); + _rows.AddRange(rows); + } + + /// + /// Adds a column to the table. + /// + /// The header of the column. + /// The icon of the column. + /// The layout of the column. + public virtual void AddColumn(string name, PropertyIcon icon = null, TypesLayoutTableRow layout = TypesLayoutTableRow.Default) + { + _columns.Add(new ControlTableColumn(null) + { + Text = name, + Icon = icon, + Layout = layout + }); + } + + /// + /// Adds one or more columns to the table. + /// + /// The columns to add. + public virtual void AddColumns(params ControlTableColumn[] columns) + { + _columns.AddRange(columns); + } + + /// + /// Adds one or more columns to the table. + /// + /// The columns to add. + public virtual void AddColumns(IEnumerable columns) + { + _columns.AddRange(columns); + } + + /// + /// Adds a row to the table. + /// + /// The cells of the row. + public void AddRow(params IControl[] cells) + { + var r = new ControlTableRow(null, cells); + + _rows.Add(r); + } + + /// + /// Adds one or more rows to the table. + /// + /// The rows to add. + public void AddRows(params ControlTableRow[] rows) + { + _rows.AddRange(rows); + } + + /// + /// Adds one or more rows to the table. + /// + /// The rows to add. + public void AddRows(IEnumerable rows) + { + _rows.AddRange(rows); + } + + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + _columns.ForEach(x => x.Layout = ColumnLayout); + var classes = Classes.ToList(); + classes.Add("table"); + + if (Striped) + { + classes.Add("table-striped"); + } + + if (Responsive) + { + classes.Add("table-responsive"); + } + + if (Reflow) + { + classes.Add("table-reflow"); + } + + var html = new HtmlElementTableTable() + { + Id = Id, + Class = string.Join(" ", classes.Where(x => !string.IsNullOrWhiteSpace(x))), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + + html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(renderContext)).ToArray()); + html.Rows.AddRange(from x in Rows select x.Render(renderContext) as HtmlElementTableTr); + + return html; + } + } +} From 1ab87fdc18d3f943a35a1e2786744e840c968a58 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 28 Dec 2024 19:53:12 +0100 Subject: [PATCH 31/59] add system plugin functionality --- .../Fixture/UnitTestControlFixture.cs | 5 ++-- .../WebComponent/ComponentHubUI.cs | 25 ------------------- .../WebComponent/IComponentHubUI.cs | 11 -------- src/WebExpress.WebUI/WebExUI.cs | 19 ++++---------- src/WebExpress.WebUI/WebExpress.WebUI.csproj | 4 +++ 5 files changed, 11 insertions(+), 53 deletions(-) delete mode 100644 src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs delete mode 100644 src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index 740fc93a..f5075b3e 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -13,7 +13,6 @@ using WebExpress.WebCore.WebPage; using WebExpress.WebCore.WebPlugin; using WebExpress.WebCore.WebUri; -using WebExpress.WebUI.WebComponent; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.Fixture @@ -59,7 +58,7 @@ public static IHttpServerContext CreateHttpServerContextMock() /// The component hub. public static ComponentHub CreateComponentHubMock() { - var ctorComponentHub = typeof(ComponentHubUI).GetConstructor + var ctorComponentHub = typeof(ComponentHub).GetConstructor ( BindingFlags.NonPublic | BindingFlags.Instance, null, @@ -70,7 +69,7 @@ public static ComponentHub CreateComponentHubMock() var componentHub = (ComponentHub)ctorComponentHub.Invoke([CreateHttpServerContextMock()]); // set static field in the webex class - var type = typeof(WebEx); + var type = typeof(WebEx); var field = type.GetField("_componentHub", BindingFlags.Static | BindingFlags.NonPublic); field.SetValue(null, componentHub); diff --git a/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs b/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs deleted file mode 100644 index 1ea848b2..00000000 --- a/src/WebExpress.WebUI/WebComponent/ComponentHubUI.cs +++ /dev/null @@ -1,25 +0,0 @@ -ο»Ώusing WebExpress.WebCore; -using WebExpress.WebCore.Internationalization; -using WebExpress.WebCore.WebComponent; - -namespace WebExpress.WebUI.WebComponent -{ - /// - /// Represents the UI component hub that inherits from . - /// - public class ComponentHubUI : ComponentHub, IComponentHubUI - { - /// - /// Initializes a new instance of the class. - /// - /// The HTTP server context. - protected ComponentHubUI(IHttpServerContext httpServerContext) - : base(httpServerContext) - { - if (InternationalizationManager is InternationalizationManager internationalizationManager) - { - internationalizationManager.Register(typeof(ComponentHubUI).Assembly, typeof(ComponentHubUI).Assembly.GetName().Name?.ToLower()); - } - } - } -} diff --git a/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs b/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs deleted file mode 100644 index 2789aba6..00000000 --- a/src/WebExpress.WebUI/WebComponent/IComponentHubUI.cs +++ /dev/null @@ -1,11 +0,0 @@ -ο»Ώusing WebExpress.WebCore.WebComponent; - -namespace WebExpress.WebUI.WebComponent -{ - /// - /// Interface for WebExpress.WebUI of the component hub. - /// - public interface IComponentHubUI : IComponentHub - { - } -} diff --git a/src/WebExpress.WebUI/WebExUI.cs b/src/WebExpress.WebUI/WebExUI.cs index 531a1255..32e78b35 100644 --- a/src/WebExpress.WebUI/WebExUI.cs +++ b/src/WebExpress.WebUI/WebExUI.cs @@ -1,25 +1,16 @@ ο»Ώusing System.Runtime.CompilerServices; -using WebExpress.WebCore; -using WebExpress.WebCore.WebComponent; -using WebExpress.WebUI.WebComponent; +using WebExpress.WebCore.WebAttribute; +[assembly: SystemPlugin()] [assembly: InternalsVisibleTo("WebExpress.WebUI.Test")] namespace WebExpress.WebUI { /// - /// Represents the WebExpress UI component that extends the WebEx class with the IComponentHubUI interface. + /// Represents the WebExUI class which is a part of the WebExpress.WebUI namespace. + /// This class is internal and is intended for use within the WebExpress.WebUI assembly. /// - public class WebExUI : WebEx + internal class WebExUI { - /// - /// Creates and returns a new instance of . - /// - /// The HTTP server context used to initialize the component manager. - /// A new instance of . - protected override IComponentHubUI CreateComponentManager(IHttpServerContext httpServerContext) - { - return ComponentActivator.CreateInstance(httpServerContext); - } } } diff --git a/src/WebExpress.WebUI/WebExpress.WebUI.csproj b/src/WebExpress.WebUI/WebExpress.WebUI.csproj index d9080054..d181ea95 100644 --- a/src/WebExpress.WebUI/WebExpress.WebUI.csproj +++ b/src/WebExpress.WebUI/WebExpress.WebUI.csproj @@ -400,4 +400,8 @@ + + + + From 09ac3c80b08ffa31b9c9c9450e83f8740d2b6e7b Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 28 Dec 2024 21:01:39 +0100 Subject: [PATCH 32/59] extend RenderContext to include current endpoint --- .../Fixture/UnitTestControlFixture.cs | 2 +- .../WebControl/RenderControlFormContext.cs | 8 +- src/WebExpress.WebUI/WebPage/PageControl.cs | 50 ----------- .../WebPage/RenderControlContext.cs | 10 +-- .../WebPage/VisualTreeControl.cs | 88 +++++++++++++++---- 5 files changed, 80 insertions(+), 78 deletions(-) diff --git a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs index f5075b3e..25f63596 100644 --- a/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs +++ b/src/WebExpress.WebUI.Test/Fixture/UnitTestControlFixture.cs @@ -194,7 +194,7 @@ public static IRenderControlContext CrerateRenderContextMock(IApplicationContext { var request = CrerateRequestMock(); - return new RenderControlContext(CreratePageContextMock(applicationContext, scopes), request); + return new RenderControlContext(null, CreratePageContextMock(applicationContext, scopes), request); } /// diff --git a/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs index ceded732..190d733f 100644 --- a/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs +++ b/src/WebExpress.WebUI/WebControl/RenderControlFormContext.cs @@ -1,4 +1,5 @@ ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebEndpoint; using WebExpress.WebCore.WebMessage; using WebExpress.WebCore.WebPage; using WebExpress.WebUI.WebPage; @@ -25,11 +26,12 @@ public class RenderControlFormContext : RenderControlContext, IRenderControlForm /// /// Initializes a new instance of the class. /// + /// The endpoint where the control is rendered. /// The page context where the control is rendered. - /// The request. + /// The request associated with the rendering context. /// The form in which the control is rendered. - public RenderControlFormContext(IPageContext pageContext, Request request, IControlForm form) - : base(pageContext, request) + public RenderControlFormContext(IEndpoint endpoint, IPageContext pageContext, Request request, IControlForm form) + : base(endpoint, pageContext, request) { Form = form; } diff --git a/src/WebExpress.WebUI/WebPage/PageControl.cs b/src/WebExpress.WebUI/WebPage/PageControl.cs index a6b936c2..3f97b040 100644 --- a/src/WebExpress.WebUI/WebPage/PageControl.cs +++ b/src/WebExpress.WebUI/WebPage/PageControl.cs @@ -32,56 +32,6 @@ public PageControl() } - ///// - ///// Initialization - ///// - ///// The context of the resource. - //public override void Initialization(IResourceContext context) - //{ - // base.Initialization(context); - - // var module = ComponentManager.ModuleManager.GetModule(context?.ModuleContext?.ApplicationContext, typeof(Module)); - // if (module != null) - // { - // var contextPath = module.ContextPath; - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/fontawesome.min.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap.min.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/solid.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.expand.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.form.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalform.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalpage.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.more.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.move.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.pagination.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.search.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.selection.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.table.css")); - // CssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.toolpanel.css")); - - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); - // HeaderScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); - // } - - // Meta.Add(new KeyValuePair("charset", "UTF-8")); - // Meta.Add(new KeyValuePair("viewport", "width=device-width, initial-scale=1")); - //} - /// /// Processing of the page. /// diff --git a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs index 1cc68a9b..ebdc7eef 100644 --- a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs +++ b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs @@ -1,4 +1,5 @@ -ο»Ώusing WebExpress.WebCore.WebMessage; +ο»Ώusing WebExpress.WebCore.WebEndpoint; +using WebExpress.WebCore.WebMessage; using WebExpress.WebCore.WebPage; namespace WebExpress.WebUI.WebPage @@ -23,7 +24,6 @@ void IRenderControlContext.AddScript(string key, string code) /// The link of the java script file. void IRenderControlContext.AddScriptLink(string url) { - } /// @@ -31,7 +31,7 @@ void IRenderControlContext.AddScriptLink(string url) /// /// The render context. public RenderControlContext(IRenderContext renderContext) - : base(renderContext?.PageContext, renderContext?.Request) + : base(renderContext?.Endpoint, renderContext?.PageContext, renderContext?.Request) { } @@ -40,8 +40,8 @@ public RenderControlContext(IRenderContext renderContext) /// /// >The page context. /// The request associated with the rendering context. - public RenderControlContext(IPageContext pageContext, Request request) - : base(pageContext, request) + public RenderControlContext(IEndpoint endpoint, IPageContext pageContext, Request request) + : base(endpoint, pageContext, request) { } } diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index 7872b72a..433c5622 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -1,8 +1,10 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.Internationalization; +using WebExpress.WebCore.WebComponent; using WebExpress.WebCore.WebHtml; using WebExpress.WebCore.WebPage; +using WebExpress.WebCore.WebUri; using WebExpress.WebUI.WebControl; namespace WebExpress.WebUI.WebPage @@ -12,6 +14,7 @@ namespace WebExpress.WebUI.WebPage /// public class VisualTreeControl : IVisualTree { + private readonly IComponentHub _componentHub; private readonly List _favicons = []; private readonly List _styles = []; private readonly List _headerScriptLinks = []; @@ -22,6 +25,11 @@ public class VisualTreeControl : IVisualTree private readonly Dictionary _meta = []; private readonly List _content = []; + /// + /// Returns the component hub. + /// + protected IComponentHub ComponentHub => _componentHub; + /// /// Returns the title of the html document. /// @@ -75,8 +83,50 @@ public class VisualTreeControl : IVisualTree /// /// Initializes a new instance of the class. /// - public VisualTreeControl() + /// The component hub. + /// The page context. + public VisualTreeControl(IComponentHub componentHub, IPageContext pageContext) { + _componentHub = componentHub; + + Title = pageContext?.PageTitle; + + var contextPath = pageContext.ContextPath; + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/fontawesome.min.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap.min.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/solid.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/summernote-bs5.min.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.expand.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.form.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalform.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.modalpage.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.more.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.move.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.pagination.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.search.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.selection.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.table.css")); + _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.toolpanel.css")); + + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); + _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); + + _meta.Add("charset", "UTF-8"); + _meta.Add("viewport", "width=device-width, initial-scale=1"); } /// @@ -84,7 +134,7 @@ public VisualTreeControl() /// /// The URL of the favicon. /// The media type of the favicon. - public void AddFavicon(string url, string mediatype) + public virtual void AddFavicon(string url, string mediatype) { _favicons.Add(new Favicon(url, mediatype)); } @@ -93,7 +143,7 @@ public void AddFavicon(string url, string mediatype) /// Removes a favicon from the web application. ///
                                                                                                                                                                                                                                                                                      /// The URL of the favicon to remove. - public void RemoveFavicon(string url) + public virtual void RemoveFavicon(string url) { _favicons.RemoveAll(x => x.Url.Equals(url)); } @@ -102,7 +152,7 @@ public void RemoveFavicon(string url) /// Adds one or more styles to the head. ///
                                                                                                                                                                                                                                                                                      /// The styles to add. - public void AddStyle(params string[] styles) + public virtual void AddStyle(params string[] styles) { _styles.AddRange(styles); } @@ -111,7 +161,7 @@ public void AddStyle(params string[] styles) /// Removes a style from the head. ///
                                                                                                                                                                                                                                                                                      /// The style to remove. - public void RemoveStyle(string style) + public virtual void RemoveStyle(string style) { _styles.RemoveAll(x => x.Equals(style)); } @@ -120,7 +170,7 @@ public void RemoveStyle(string style) /// Adds one or more URLs to the list of header script links. ///
                                                                                                                                                                                                                                                                                      /// The URLs of the script to add. - public void AddHeaderScriptLink(params string[] urls) + public virtual void AddHeaderScriptLink(params string[] urls) { _headerScriptLinks.AddRange(urls); } @@ -129,7 +179,7 @@ public void AddHeaderScriptLink(params string[] urls) /// Removes a URL from the list of header script links. ///
                                                                                                                                                                                                                                                                                      /// The URL of the script to remove. - public void RemoveHeaderScriptLink(string url) + public virtual void RemoveHeaderScriptLink(string url) { _headerScriptLinks.RemoveAll(x => x.Equals(url)); } @@ -138,7 +188,7 @@ public void RemoveHeaderScriptLink(string url) /// Adds one or more URLs to the list of script links. ///
                                                                                                                                                                                                                                                                                      /// The URLs of the script to add. - public void AddScriptLink(params string[] urls) + public virtual void AddScriptLink(params string[] urls) { _scriptLinks.AddRange(urls); } @@ -147,7 +197,7 @@ public void AddScriptLink(params string[] urls) /// Removes a URL from the list of script links. ///
                                                                                                                                                                                                                                                                                      /// The URL of the script to remove. - public void RemoveScriptLink(string url) + public virtual void RemoveScriptLink(string url) { _scriptLinks.RemoveAll(x => x.Equals(url)); } @@ -156,7 +206,7 @@ public void RemoveScriptLink(string url) /// Adds one or more URLs to the list of header scripts. ///
                                                                                                                                                                                                                                                                                      /// The URLs of the script to add. - public void AddHeaderScript(params string[] urls) + public virtual void AddHeaderScript(params string[] urls) { _headerScripts.AddRange(urls); } @@ -165,7 +215,7 @@ public void AddHeaderScript(params string[] urls) /// Removes a URL from the list of header scripts. ///
                                                                                                                                                                                                                                                                                      /// The URL of the script to remove. - public void RemoveHeaderScript(string url) + public virtual void RemoveHeaderScript(string url) { _headerScripts.RemoveAll(x => x.Equals(url)); } @@ -175,7 +225,7 @@ public void RemoveHeaderScript(string url) ///
                                                                                                                                                                                                                                                                                      /// The identifier of the script. /// The script content. - public void AddScript(string id, string script) + public virtual void AddScript(string id, string script) { _scripts[id] = script; } @@ -184,7 +234,7 @@ public void AddScript(string id, string script) /// Removes a script from the collection. ///
                                                                                                                                                                                                                                                                                      /// The identifier of the script to remove. - public void RemoveScript(string id) + public virtual void RemoveScript(string id) { _scripts.Remove(id); } @@ -193,7 +243,7 @@ public void RemoveScript(string id) /// Adds one or more URLs to the list of CSS links. ///
                                                                                                                                                                                                                                                                                      /// The URLs of the CSS file to add. - public void AddCssLink(params string[] urls) + public virtual void AddCssLink(params string[] urls) { _cssLinks.AddRange(urls); } @@ -202,7 +252,7 @@ public void AddCssLink(params string[] urls) /// Removes all CSS links that match the specified URL. ///
                                                                                                                                                                                                                                                                                      /// The URL of the CSS link to remove. - public void RemoveCssLink(string url) + public virtual void RemoveCssLink(string url) { _cssLinks.RemoveAll(x => x.Equals(url)); } @@ -212,7 +262,7 @@ public void RemoveCssLink(string url) ///
                                                                                                                                                                                                                                                                                      /// The name of the meta tag. /// The content of the meta tag. - public void AddMeta(string name, string content) + public virtual void AddMeta(string name, string content) { _meta[name] = content; } @@ -221,7 +271,7 @@ public void AddMeta(string name, string content) /// Removes a meta tag from the collection. ///
                                                                                                                                                                                                                                                                                      /// The name of the meta tag to remove. - public void RemoveMeta(string name) + public virtual void RemoveMeta(string name) { _meta.Remove(name); } @@ -230,7 +280,7 @@ public void RemoveMeta(string name) /// Adds one or more controls to the content of the page. ///
                                                                                                                                                                                                                                                                                      /// The controls to add to the content. - public void AddContent(params IControl[] controls) + public virtual void AddContent(params IControl[] controls) { _content.AddRange(controls); } @@ -239,7 +289,7 @@ public void AddContent(params IControl[] controls) /// Removes a control from the content of the page. ///
                                                                                                                                                                                                                                                                                      /// The control to remove from the content. - public void RemoveContent(IControl control) + public virtual void RemoveContent(IControl control) { _content.Remove(control); } From f67ff74d2b9639924010c4cb50b3cc5766e63aa4 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 28 Dec 2024 22:05:14 +0100 Subject: [PATCH 33/59] add: IControl interface implementation --- src/WebExpress.WebUI/WebFragment/IFragmentControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs index 7d513c28..bd4d3444 100644 --- a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs +++ b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs @@ -15,7 +15,7 @@ public interface IFragmentControl : IFragmentControl /// Represents a fragment interface with a generic type parameter. ///
                                                                                                                                                                                                                                                                                      /// The type of control that implements the IControl interface. - public interface IFragmentControl : IFragment where T : class, IControl + public interface IFragmentControl : IFragment, IControl where T : class, IControl { /// /// Gets the context of the fragment. From a8b9270999116b4a7eb838cdfc173502f27b00aa Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 29 Dec 2024 12:28:00 +0100 Subject: [PATCH 34/59] refactor: update IFragmentControl interface - the IFragmentControl interface now directly inherits from IFragment - the generic interface IFragmentControl now inherits from IFragmentControl --- .../WebControl/ControlPanel.cs | 264 +++++++++--------- .../WebFragment/IFragmentControl.cs | 6 +- 2 files changed, 141 insertions(+), 129 deletions(-) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 755feae3..9c99594e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -1,126 +1,138 @@ -ο»Ώusing System.Collections.Generic; -using System.Linq; -using WebExpress.WebCore.WebHtml; -using WebExpress.WebUI.WebPage; - -namespace WebExpress.WebUI.WebControl -{ - /// - /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. - /// - public class ControlPanel : Control - { - private readonly List _content = []; - - /// - /// Returns the content of the panel. - /// - /// - /// The content property holds a collection of controls that represent the visual and interactive elements - /// within this container. - /// - public IEnumerable Content => _content; - - /// - /// Returns or sets the arrangement of the content. - /// - public TypeDirection Direction - { - get => (TypeDirection)GetProperty(TypeDirection.Default); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Fixed or full-width adjustment. - /// - public TypePanelContainer Fluid - { - get => (TypePanelContainer)GetProperty(TypePanelContainer.None); - set => SetProperty(value, () => value.ToClass()); - } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the control. - /// The child controls to be added to the panel. - public ControlPanel(string id = null, params IControl[] controls) - : base(id) - { - _content.AddRange(controls.Where(x => x != null)); - } - - /// - /// Adds one or more controls to the content of the control panel. - /// - /// The controls to add to the content. - /// - /// This method allows adding one or multiple controls to the collection of - /// the control panel. It is useful for dynamically constructing the user interface by appending - /// various controls to the panel's content. - /// Example usage: - /// - /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "A" }; - /// var text2 = new ControlText { Text = "B" }; - /// panel.Add(text1, text2); - /// - /// This method accepts any control that implements the interface. - /// - public virtual void Add(params IControl[] controls) - { - _content.AddRange(controls); - } - - /// - /// Adds one or more controls to the content of the control panel. - /// - /// The controls to add to the content. - /// - /// This method allows adding one or multiple controls to the collection of - /// the control panel. It is useful for dynamically constructing the user interface by appending - /// various controls to the panel's content. - /// Example usage: - /// - /// var panel = new ControlPanel(); - /// var text1 = new ControlText { Text = "A" }; - /// var text2 = new ControlText { Text = "B" }; - /// panel.Add(new List([text1, text2])); - /// - /// This method accepts any control that implements the interface. - /// - public virtual void Add(IEnumerable controls) - { - _content.AddRange(controls); - } - - /// - /// Removes a control from the content of the control panel. - /// - /// The control to remove from the content. - /// - /// This method allows removing a specific control from the collection of - /// the control panel. - /// - public virtual void Remove(IControl control) - { - _content.Remove(control); - } - - /// - /// Convert the control to HTML. - /// - /// The context in which the control is rendered. - /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) - { - return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) - { - Id = Id, - Class = GetClasses(), - Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), - Role = Role - }; - } - } -} +ο»Ώusing System.Collections.Generic; +using System.Linq; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.WebControl +{ + /// + /// Represents a control panel that can contain multiple child controls and manage their layout and rendering. + /// + public class ControlPanel : Control + { + private readonly List _content = []; + + /// + /// Returns the content of the panel. + /// + /// + /// The content property holds a collection of controls that represent the visual and interactive elements + /// within this container. + /// + public IEnumerable Content => _content; + + /// + /// Returns or sets the arrangement of the content. + /// + public TypeDirection Direction + { + get => (TypeDirection)GetProperty(TypeDirection.Default); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Fixed or full-width adjustment. + /// + public TypePanelContainer Fluid + { + get => (TypePanelContainer)GetProperty(TypePanelContainer.None); + set => SetProperty(value, () => value.ToClass()); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id of the control. + /// The child controls to be added to the panel. + public ControlPanel(string id = null, params IControl[] controls) + : base(id) + { + _content.AddRange(controls.Where(x => x != null)); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(text1, text2); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(params IControl[] controls) + { + _content.AddRange(controls); + } + + /// + /// Adds one or more controls to the content of the control panel. + /// + /// The controls to add to the content. + /// + /// This method allows adding one or multiple controls to the collection of + /// the control panel. It is useful for dynamically constructing the user interface by appending + /// various controls to the panel's content. + /// Example usage: + /// + /// var panel = new ControlPanel(); + /// var text1 = new ControlText { Text = "A" }; + /// var text2 = new ControlText { Text = "B" }; + /// panel.Add(new List([text1, text2])); + /// + /// This method accepts any control that implements the interface. + /// + public virtual void Add(IEnumerable controls) + { + _content.AddRange(controls); + } + + /// + /// Removes a control from the content of the control panel. + /// + /// The control to remove from the content. + /// + /// This method allows removing a specific control from the collection of + /// the control panel. + /// + public virtual void Remove(IControl control) + { + _content.Remove(control); + } + + + /// + /// Clears all controls from the content of the control panel. + /// + /// + /// This method removes all controls from the collection of the control panel. + /// It is useful for resetting the panel's content to an empty state. + /// + public virtual void Clear() + { + _content.Clear(); + } + /// + /// Convert the control to HTML. + /// + /// The context in which the control is rendered. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext) + { + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + { + Id = Id, + Class = GetClasses(), + Style = string.Join("; ", Styles.Where(x => !string.IsNullOrWhiteSpace(x))), + Role = Role + }; + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs index bd4d3444..ebc93ec9 100644 --- a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs +++ b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs @@ -5,9 +5,9 @@ namespace WebExpress.WebUI.WebFragment { /// - /// Represents a fragment interface with a generic type parameter. + /// Represents a fragment control interface. /// - public interface IFragmentControl : IFragmentControl + public interface IFragmentControl : IFragment, IControl { } @@ -15,7 +15,7 @@ public interface IFragmentControl : IFragmentControl /// Represents a fragment interface with a generic type parameter. /// /// The type of control that implements the IControl interface. - public interface IFragmentControl : IFragment, IControl where T : class, IControl + public interface IFragmentControl : IFragmentControl where T : class, IControl { /// /// Gets the context of the fragment. From 989ede576bc443f25664217646a70ba741f970cd Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 29 Dec 2024 14:24:59 +0100 Subject: [PATCH 35/59] chore: add automation for generating API documentation with DocFX --- .github/workflows/generate-docs.yml | 52 +++++++++++++++++ README.md | 2 + docs/api/toc.yml | 2 + docs/assets/webexpress.ico | Bin 0 -> 70141 bytes docs/assets/webexpress.svg | 40 +++++++++++++ docs/docfx.json | 61 ++++++++++++++++++++ docs/index.md | 30 ++++++++++ docs/template/dashboard.html.tmpl | 47 +++++++++++++++ docs/template/public/main.css | 10 ++++ docs/template/public/main.js | 14 +++++ docs/template/schemas/Dashboard.schema.json | 45 +++++++++++++++ docs/toc.yml | 8 +++ docs/tutorials.md | 17 ++++++ docs/user-guide.md | 15 +++++ 14 files changed, 343 insertions(+) create mode 100644 .github/workflows/generate-docs.yml create mode 100644 docs/api/toc.yml create mode 100644 docs/assets/webexpress.ico create mode 100644 docs/assets/webexpress.svg create mode 100644 docs/docfx.json create mode 100644 docs/index.md create mode 100644 docs/template/dashboard.html.tmpl create mode 100644 docs/template/public/main.css create mode 100644 docs/template/public/main.js create mode 100644 docs/template/schemas/Dashboard.schema.json create mode 100644 docs/toc.yml create mode 100644 docs/tutorials.md create mode 100644 docs/user-guide.md diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml new file mode 100644 index 00000000..23b23923 --- /dev/null +++ b/.github/workflows/generate-docs.yml @@ -0,0 +1,52 @@ +name: Generate and Deploy Documentation + +on: + push: + branches: + - develop + +permissions: + actions: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + publish-docs: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 9.x + + - name: Install DocFX + run: dotnet tool install -g docfx + + - name: Add DocFX to PATH + run: echo "$HOME/.dotnet/tools" >> $GITHUB_PATH + + - name: Generate documentation + run: | + cd docs + docfx metadata + docfx build + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: '_site' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index fa873627..f4439fe2 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ The current binaries are available for download [here](https://github.com/ReneSc # Start If you're looking to get started with `WebExpress`, we would recommend using the following documentation. It can help you understand the platform. +- [WebExpress.WebCore API Documentation](https://reneschwarzer.github.io/WebExpress.WebCore/) +- [WebExpress.WebUI API Documentation](https://reneschwarzer.github.io/WebExpress.WebUI/) - [installation guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/installation_guide.md) - [development guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/development_guide.md) diff --git a/docs/api/toc.yml b/docs/api/toc.yml new file mode 100644 index 00000000..20c32afa --- /dev/null +++ b/docs/api/toc.yml @@ -0,0 +1,2 @@ +### YamlMime:TableOfContent +[] diff --git a/docs/assets/webexpress.ico b/docs/assets/webexpress.ico new file mode 100644 index 0000000000000000000000000000000000000000..c0909c98b13c6125b7254544eaa2a1d91238b006 GIT binary patch literal 70141 zcmeI52|QIz|G>vC;Zl(bA*G}!m84Kw5iPQ2i9#w;l8_}k*(ys#)+EZlMA_FQTgbjg zS;|hf`=4_?-S^SegLf*y6=Qzqqx;%6sY8G83sf z2$368aFl1QWaU_yZF^9Z`~UN_ta+o;BKWt9NZB zv3OzQT25k>a%US4AMv^a8g#A89rp{fQ}zv7ozR|e2rED2SW40wbyJO5z1XJt`}NmV zpQ%CTW~&r2zAfBjt>oG4n>JFFrUuXnIc(`q^z$85V%}0HDtiO6Rd(mekn6P64~X_= z*+>2%@E-lw<Kh=if`&N ztI4t0{Y;>3W3F|!+NDl$Ny@baxoW^Ii1OM%X2_lM@14M?c0U}U-f(0?b&oLj4sKR$7@PR;oU;~@2%bge{+#f*sfrTXx%an`-2>>8ym-57+DR-0g*+blaR1t6zg-VBfATQ zy>`kBr1Jx9dp+}R)hO0u>{iS=X`kxFSxw0;G$g3))8DRteB9VewX*VVtiW}*llm+b zEXQBTDw97AS#!V=d{tjbP2+MfPMY%Goj^W84*IP{_k^oQl#a)D18R`BbMIBUGEdz* zk&mC1)}9Kl*sbVo>08ZpHH2p+OPDJ5Mv9Ew!~k~u^>CKY=jhSf1(J7Zo#H=Fc_mgx zF9&pLVqu=|o7B=Krs#L4bYB=vUL!CXuee1x$(UBDOeE*#&YYA6mlJH+alM?EeN&0E z?r^+M#d3R45k>MGj18=B9w(L~GvwQ3d2++5iHesr-bv#MJbMQ3owQmDb|})6iKk`R zn+w~fJ!zovsCnc1IjoI_c>QT_q*DV=E1> zg*jGlVgfGgnVTu|SgW)LdChN~-qLP1L9FZ_dx8p&ahrrX!>izZ%1Gi;Twin$x$e=0GQ-@v?0n$VJ!j5}9R=fbIv0*(|EU zy&Se=Yq0V?li$iEa!A3?hgr2(Ds(p@JmUZ%VgBAm3eTaI;8xf`y5iRkUZ8t{t7%o#G zuHteRwIBIvR>leIi?+=?=ws7LDr=)_svO&q*`Wnj{0M@qpy;eOW3e(|fN$R*d)4h?3> zNvIxB7qu>mDbQsYZhx}N*t|^dQ*00)=)T^Yw(B;7?A<3*W`30N=honM~G7+H;Z|^vGlbeQd4Ejski+2P4QBH zkIM71$)UQ7^lzC~uQ)f@IM!40madDE-dWblr?UZj$M2QC15V@K#Jb*MLFtTR=f}8` zlZ>eoY{b6ty=|l#8q5ohI=AN?!_NAzLyfyt9=xR;P#t9zT}#>5YZIHlL|1*~?n^c$ zI&l`@>a}YJQu^(LzP>D=-O*`uaMunt=8F=$9`|VY+%SIeSisQYOM73QkzJF4f|Tn8 zDxCt8_?~t{!AR^Xz^HpRfU;FgW7{TECUsK^wewgeBZ<1Ej;~J##2zVgGw9T;4xk6s ziF%@y)s9Yy{qAz79k<_N@vmqZC0X-6Su;&Ec$~EK(B))?+sh7+6IJi?I;mqKaAq|8 zarM5fGVqu5!$k7y?`meu;cr!(eN7p@nT%8}bk#9_|=aqqEhs2Qx^(BW_8zr#I88)52xJ!ta#DC;$ z&a%DxbXX%ql9x*#f3>nqSn*v$*#_&JtTTDaX7H|QG*4ymRZdCEn!57k%tUK}zVD|H zYpy`Q@Ynlmg-!Pa{*`RVn%2g#jZu$G01e>uKIDk}3pzKF_ilgf#crwqjE4NteDjqxX_k zT&g0xj_YHwMyciTP=O}pNvBUA`G!-tN`fzcP}o&fPchKCfk|fMg(Go_F3+Cr4Wtuf z8VA&)Zf5K`IA*)sRH@MEv4v3@Ut3qSOM@2KmsbX_DQlmJ+<90U)YRVH@AN55admHJ zj+N1tE`Ecqq=rVnyhgp=HLkT=nM=9~Gu`zM!N(!XGRnTZZA+u{JGbu^a;Rn#8Jket z)6P<*U7|*1FpxVK+I*DyuJ!AKR30H~UOF23Y<`!O$nc#!#bae#yG@ttS8FdBY!|jb zbCr67v9}(!k6KhjWtl+tqj9b}79mgPKGm-dYwT?F??;JXeHySK2`Nin_or?@wlQsA zm%bIb2zX;Ur9o@fKvGhy=11qFFt(k-9Mj+(Pp)r9!ZUSKZo~U@pV2<@$;Sold%6pc zx9-;fpBcN`t@z(1un8LQnTTOb>-Xw6rFJy8swZ)=52)uhJ6GFAUXL2eBr-6(+2_9v z431yu`u3&xiND>ebj#gIqk6sfA7SG=Ojo zNvPM-SrsxwcE!7C=|z4=PU6T&gx%}d<}T*TW11q7ldHhkz||WXynH8urTMn*eZwN{ z@@Q#5x`Fb>l8U8%Jo2tL+l4E_carnUF}9E_uQNIicDoHr6)o$c5pY;htM&5mSiju1 zeH=NVY*!ft&)q2CIcq++kB4c`bGh0R;T7^G6UT)|1l+Pj$oI-VaIkSmJ1715X(@?@ zzIwH0+Zivl#){agn?pR@Z9~SsovvMLoyJ?a&go~a2zqup?csO9m@p?JQR=o{UgATy zDAr8|^k^z8zH`@(SA4KTmOVTMe0qOlO6x8_mecGs)D{6Lb4c)}p=eSY!{7V|M3t~Gav)H3O+;#qI(T^?n;{T4r?c>-C1 z%8UJ?)E2B_Y#v@Dvd3SZ)Og#xWutDGx&|L8yeXK@Pt+CH(rXy((VOf?q-M!)xu;=y z6n8BzbGDtFbS%51wJXt$qtgws_hU~)?E;q%Q3*!KdWeQ-AJVX6zTjN(Sth(>O9^pF zV6?JJt@91ap*}l1r!{YUf{#+KvUU$BJxb}gV?6KZiwvPvN1`|MtTnB5B~p9M&UWe2 zVcqw~+sYrXrKK{jEEv##{W2qT3D17r26-lP3QtbSoZhKY!&}r1@AkMHNo@;HrM3{h z*Rt?{(FK=%*cP-@sS8T3g6P8Z$r%f)ydaFKx-eB$W7_T zx&t@)UC-^L5Ftr7E+Wm;*ZCrWr6*qPO#UUYzwcbpCgx3r7B6CRxI1eavoI9j%vpoT zsiWT}G`RN(vL3I^$S4L;MRX?&!=v~+NQHR|MGcQToT;oh-hHQjz%S!XRo||PT%kyx z^a71YeOQSv?x%%wJz8<)b7knu)QBREZL|$oX3f02(GCgqM!LKzqsADDwDnt8R+FZz z>(Y*P$iM()9R^S4nmayW>fsU34hLmCT8GOizx}M1gjk;*OgM&FVQj zeIoOZ+)xT?Fb|4~US=*ByR=p_A|~wiH<=sf-uHd%%QzF!k!J#i%?j4jan$kCl?t%(zABu`-%hoQ}6iNz*eZ3h{I;2$&(b_%D0|l$+GC!oT-GPoSEYT zSbM|xWfV)d4$3EpJp07V!|kB<mwFC9dkJ77t7ntVgkTiA=^ zH-1ndnMc#v;Usc5Wo5DNq<`Kug$kP!2Ai5&c%tR&8PcDx$m2I$4^|S+j;(O#rqu9Cq~bTc!zduuF(%ar0G5uTA?%XCHu9}L|ZNM#9opp zWwA+$milUGweEDI@CdC?FOk4Ecdm-%J-StWMu4uTv9WvT`wr~hgbU2)Dbzt#M79N` zk3s^OulDmN>| zitclJj!QO(I)2QOo{5F=l9C7G=dJ3`ZxN}xFE?G!+I^H7)IOkFanZ!1vbCdLtVJhD zBGhf8AtyOd5cdkH4eR8u60)X%&Cth1Ubivv&V`fMV|L;Jc^NC^UkKBuQUh`eXYPv; zxt0?HhKZ_0jC&`Fx^<|5Qo``)n*1c?%lt!I+`l|wV+{Z*}nDZ=KyrTv#h6^uu+oX7-fppNrI6bf88t*QfLPM8>uh-& z8jo%^YB27_yE!la=Gv~O-`=BB?DXyHX(lL9dpU|5HH16nYJK_`hlea@Efq4f;QI37_^O^q?Bw;GLZl?=+rBN4{NA)G zR)j+)ykazP^j^`m`xG1G-_UH|ywtx`r)m}Ku|D6=p69FiMBFrj2NNSz&s$r!MxeB1 z+&qrY%GZJ@-GsQ^NBj-1^oX40D6V--dfy!56hTk62F)gnKhOiV{B}^ouqZEWEB`(J3=bC z*JISfpuVww=?HatdH#8)uUe;{G21zo-Aac766}1~<*m<_b<}Om&8bcHi{_OOkN-@} z2ClXl@2MG*f8xUgXiWs&;xytN!Eki=}0Y>=KY%Bgfy&m zkvF^Qoai>{y~ub**4W7-u#JcHq*(xCePkBdm;8uL%|x2OZR?QlOXMcF7EZHb#gw8`>uhjH$K`xpGLlxy!Aw4R3m2{(QLNtOm1a7fiv8KEqq@uEEZe-zhn zr9i51@-wgLpq3bEm0Q>aetBNGXi_3w6_K+eiTRSd!nc-+5OaCy9=5PceA_uT=%uG& z(yp~v`wc1EeP5c;2OBR%98$Rc^4PQT_5yMDWRrcJHIml_uLg9RyvgmDq6RT6u!nTC z{=&pQOP8%=tb)U0*WIp=t$_{53JPun3{Ag%%YLb~_m|s}p*?h#-8#^3a;**~PjktUkM_{e4vrm?Iv8<4 z?aoFRwm>4F6&^AB&$k^m2k0M4040DDKnb7(Py#3clmJQqC4dq@37`Z}0w@8L07?KQ zfD%9npaf6?C;^lJN&qE*5KY=4^4w42z8q~E9VrO9hp}ZOQ?v3=Ob`zt~(#kv#>6iQ1MaH4SdqV zfr-g+d8gHcx@dSd0r5LzZ>!@MAPF&^by>;#3u+P;1~{Es-jqYA_$%H5H*Q z8lENq;m>aE%tv)%V&atDGCVrtz@zg?&W^w8vj?w;27bUNTjZUO=V=orkEbVNzXCQd z@kt8@>|dP4E205N06uURf9K=bzQ}PVq}TDa5udbhz$+0oO8;x3A^5<3TeDDWXFix8 znlcIb=U2zgCpjbDH~AK!;_n=WoveT3&Y$M_ZSV^rx|g{wGdRz8i1MH22F(le^>F7y zM;H%(@ChxV-ii8zsSAWX6LbkH?zauUE)HCP(qfX%y0GEtS%u0jMg__^MyTSoe%pYG zEBoSGEc1cA@L)3@pvAKj^NG!fHx4|4*ZOS(YVMpfu>2c`7rprK0L`9CE;0vY7k0eX z?;Lnnle9=;^NDGBZp8y!R#y;cPp&7w9*{HL(Z87u+Ws-{g2(yaHzfYLDK)9=~P1ECFUmU_re%tU- zOVV3`M-mHtz72LRfDWJ3^ts}U0|Oq{Q48YE-d23-PXq8v2aCh2qX9etXob7{a93ce zMSfLWPk+bkHWD03&;1xJ>&S>#fq_N-_!HI(^b4|nE=QON8lFwyq%G#c1MZvt2X8-> zgpf^xB^B>7&k%$5su zF~?sobR8KQ?awR^HwhAl<_LWJA_Ee4D3Xi)XH)&FF)yHl=G8Gbu`gWaj6 zA<#Il;>NL7 z8t=j<|Nj~O^tTMQ2hQEwu<%vzJVaA8BUx#{j&d}7a@3VI?(A;7) zXIDY=TaU%){)1#Bt(W{ATfuC?3&;E=KdWaMGd&pL147A}d+eOD~dqUx(s@As^ExFKlOUdO=qcHG?=<_TOu83T>MPAfDOYHo8?(*iGzYlqV z9Ip8a6Ebm+(Vo%tfPUnj+i*SQ2zY2X~rf0M-Jf# z7t9~e>bkG+kMGR|%x+>6t}=kvc8fNesLc-{7%`u_-ad?v7kPspmE zCJ~=BBM_W+hfs3%t4yVh8H57=lVNDXH}pT4T;%`L!AICinIM>3UXI)lW&{G}l-$Cs+J zo9l#NQ%XY!sTS7G>u3~~?L;Wq__>@gpXu<7Uo%4a-!>eWYCanjKBnVq10flsfJ1ZE z7iz3lmX#L~(_XHbIQ0yxkN9lhGRYoYI!Hi7TxbZ+$>rSs)> z|9`p_Is??=58;sgd~c1xyWQ;R@x^BazaaC$hw-rmUW?D_w~~~$p)PI6m=hiBUR{2; zsF{~$cmmAMt*r4+?>hZfgnxRmQa03(&unNg1{xV4+XZrfT@TNAy*VGdgc*MA|GYpZ zXp)rmyj1`(!r2V2KM^6cNI+unrAz2dSJ9kH$a%gn{56xdp+Pw>Kmb-jLCvfA0K)jL z-nQJ2G12)RF>k#JYm<8iyA}|houqMZ;{v6lNss_+5kZUbjCSU1lK)=J41+2Pd_Dqq zLS+Vqzx{iV7tpeNc51#7(fAnzLNUj*AQ#TlibhYJ%hcp?HvyB4^m|5DQ3 zNVSEFLsRD@0PUsowN6p~a}xU%kvd-6;@&-kFW>zo=7hrN{r~st1vZf2Ko4w!{u?81 z@Ui~)PXNsUPe9F$(=kE?wpU9UQepRY;fFOGr-s&Pye=B}j}w6Ih}xcfCP5N+Bh()z zUiVEl4otI{{_~8#D(krNKVBl5AxZ!xfD%9npaf6?C;^lJN&qE*51d>t^@$!>(n5t;srQmM+ZVOtO1-L z3*>%`0@h)2;OpQQm`50Z3ts@Zlqcx!`vl-}833-t1mfR41aRVZP}flcuKDf*aGFv8 zXOjbM-8H~JFi%-{UT#45(Qa_og%zIDYXGMO0l8H% z0IpmK%tE99oYDsPB;N#|zcqo9hBR05;klwH_> zjQt8&-WmWGzyRe<+2C2GEr`r_2f^ugATL?~Cy4_Ig^xj6SqOk{$O9ek?T`a8fXm4P zn=pA$So;dV>9K&O#})wJ7Y1V!qrf&?5nS}z207P*@SM9ajR(M2RY7E)8;FJ104KEs z@r927TrCUq4RwR(*$x2Cz7F!MVgX#T81xT!131|?vT7v^_W-@eg0LPz_ZZje<$+`2WSt3{5u&01O`Dhs7^~8{PeG9 z;Oj&C1OPuootD=BFYCKHLA52|F;1PwEqc{ppiO6y3qSY5n=zkFzs&M9@udcY*VCz-6}ByfL;vv}tMW zfc^A=!@Sb76D;rGGq3{I(_x$0V)MtS8k?Bn)Ff{MvuS;Ei}}UpO1XA@oxu&mo4{!G zALnx5)?8w9$6Z;=_D6!?)j!nXhyL8cvt!i{&}wO4B-Xif`HJqp)M;t;W{b`hgZsu2 z>fythbBWK4gQd^jmYrJ$BQ?&?6rSVw>}+ji6+xh?wu6@T+#0EfB-T302l_z)5gzMD#Z;AU#LYN*1WYx)uO7c6jx0TQ`T$LQyN35Uo|K z*B~EoV_ryj&a@Q_)0)%&8RwK)Fp`cQx%vOtmML0fhW*(8BMH3N|kdl#8 zP%inIAexR6Knb7(Py)XPfsODo`QWYw_n+H|DWN@Z12FVI03IjZ0Iy2|L2*MWsQL6B z)IyuBYxD&mVMT$nPi9v}fcCHT050)`vlSQA#N+I_>Ci4b{JkG%Z$)f`>dm0X6q^(C*2Hvymb; z&vW ziGS*;1<$h_aCYxjXwyaPrig7_){zn9RmXrQZ;YYMmkioMB|&pnCA5*o!ZZeO`QZ*| zKmUfa4IeQlf;_U|wRYm{+S1StuHwc4@~h(@=R%+e?Z0r{X;4^~gtIXt_VRjYOGj+S zaA824{rND=L)D!VXJen7ngC&0jyPNMCGQatd5ORv3?|rF9?CxrQT(aGRplp8((kH2{ErDB`l-D4Lqzb=V;|(h z*YYRw_wFx8{xkV&OB=zqU$zDdTl$GP{VA$J{hp2#o3H^cJ{_G=2!;K9`@rpa~6RI+y0X1|>rIv&t$!QB`fjIrVwvrB5(%|4`wE zwj!A`vU2hYOXt6f_8(vnJ9y~u5vX)@4>*Rwh)YOfj!Vs3008_ucJ30`&49rO?g2s= z473knL_`;mpHAAii5s&SvEHoX+lIj`!gjNk4a3d>Z7iJYH()SaKg}Ni#+4W*XkB4u zftSL%2zfxiY&ong+{UmNd4My1;Nq);)Gz(0fl(obcByC~d$)=yP* zUIRQ5u7LFN=eT|;;?INlBO(1T#GeM~uOR+Qh#$@c=+}by*$jUlfPFW6*yp(dDq$a_ zq9q6R5jk=F55zwSu0aaiW3_R8N5q#Ysn`!FIkVvUqb|`JI6oewzl-$S5T6*tKj=}C z0g!iE1^scJ;reEXzYWsALi){!p9|uL6aDr+uK$JjIwAchq~ClR`YIv)z&p^-2QJ+V z`&QR+eIBHLiTD$FB7bX`X=>=T~B z`79y+NQ%zPus{3^*AGN|rw~6I%V#HXeW~JxH@JSZJ?!HmK1Si$PPo1*;@gAt*$`hY z#DB;F$|u0SEz<8s`nWA!A7QPa8%h8r@c)g#PUUU$o|1whP@A9|jh&!S=|X`a>ZZws9)199X!tXWSyxL1sl*oMVJ47LkQEXe{*W z#_diKYPh(C@__d7IOs2plP_z^jDx<&czqz!OMFlT*X5BZ`_aa zkx%GPKIb{4e|Y{UT|^cxE{lbWivLMJxj0}>eYlJxzT6+>L7OwSyRTj0$1(DmUlli} z{^aB&LqSbqoNKfu_VUAB*b5JMuqmZaXPrMBqrgJH@;@=P)r=(uxX~-&q$nY~N51E)VFN zKC6sB>j5lWlNbAKpfe6$rvmg%#~!mJ$GXR8<5+a|w#GsGKlZR0(VY3faSB{n(4QZR zTu*I#G48%V@_>H)xO0FE6xw?l;$V9g3;p_$dX78mvKE)$DZ6Db8LJ>|LyJ2`(w}A8 z;li;6-gDLmBH!HkF;2#T0VfB?7qI2cIdPGB_ps3BZw~#`aq;#q&d#a-;~t0OKye5k zgd0*nFLPb7aO?x8i!eg!`iJa%pU6FL_d*GK#NuD~_7A?QZk#{W|B)|p--PElV=dsl z3fucw=aOw1n!6d4B6pk0rye3Pr)527@H2j{{a?k BFy8 + + + + + + + + + template + + + Tabelle.2 + + + + Tabelle.35 + + + + diff --git a/docs/docfx.json b/docs/docfx.json new file mode 100644 index 00000000..822538c8 --- /dev/null +++ b/docs/docfx.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json", + "metadata": [ + { + "src": [ + { + "files": [ + "src/WebExpress.WebUI/*.csproj" + ], + "src": "../" + } + ], + "dest": "api", + "outputFormat": "apiPage" + } + ], + "build": { + "content": [ + { + "files": [ "**/*.{md,yml}" ], + "exclude": [ "_site/**", "obj/**" ] + } + ], + "resource": [ + { + "files": [ "**/images/**", "**/media/**", "codesnippet/**" ], + "exclude": [ "_site/**", "obj/**" ] + }, + { + "files": [ "assets/webexpress.ico", "assets/webexpress.svg" ] + }, + { + "src": "../schemas", + "files": [ "**/*.json" ], + "dest": "schemas" + } + ], + "postProcessors": [ "ExtractSearchIndex" ], + "globalMetadata": { + "_appTitle": "WebExpress.WebUI", + "_appName": "WebExpress.WebUI", + "_appFaviconPath": "assets/webexpress.ico", + "_appLogoPath": "assets/webexpress.svg", + "pdf": false + }, + "markdownEngineProperties": { + "alerts": { + "TODO": "alert alert-secondary" + } + }, + "xref": [ + "../.xrefmap.json" + ], + "output": "../_site", + "template": [ + "default", + "modern", + "template" + ] + } +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..07712048 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,30 @@ +![WebExpress](https://raw.githubusercontent.com/ReneSchwarzer/WebExpress/main/assets/banner.png) + +# WebExpress + +WebExpress is a lightweight web server optimized for use in low-performance environments (e.g. Raspberry PI). By providing +a powerful plugin system and a comprehensive API, web applications can be easily and quickly integrated into a .NET +language (e.g. C#). Some advantages of WebExpress are: + +- It is easy to use. +- It offers a variety of features and tools that can help you build and manage your website. +- It is fast and efficient and can help you save time and money. +- It is flexible and can be customized to meet your specific requirements. + +The WebExpress family includes the following projects: + +- [WebExpress](https://github.com/ReneSchwarzer/WebExpress#readme) - The web server for WebExpress applications and the documentation. +- [WebExpress.WebCore](https://github.com/ReneSchwarzer/WebExpress.WebCore#readme) - The core for WebExpress applications. +- [WebExpress.WebUI](https://github.com/ReneSchwarzer/WebExpress.WebUI#readme) - Common templates and controls for WebExpress applications. +- [WebExpress.WebIndex](https://github.com/ReneSchwarzer/WebExpress.WebIndex#readme) - Reverse index for WebExpress applications. +- [WebExpress.WebApp](https://github.com/ReneSchwarzer/WebExpress.WebApp#readme) - Business application template for WebExpress applications. + +# WebExpress.WebUI +`WebExpress.WebUI` is part of the WebExpress family. It provides templates and controls that standardize and facilitate the +creation of web pages. + +# Download +The current binaries are available for download [here](https://github.com/ReneSchwarzer/WebExpress/releases). + +# Tags +#WebUI #WebExpress #DotNet #NETCore diff --git a/docs/template/dashboard.html.tmpl b/docs/template/dashboard.html.tmpl new file mode 100644 index 00000000..0288fe86 --- /dev/null +++ b/docs/template/dashboard.html.tmpl @@ -0,0 +1,47 @@ +{{!Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license.}} +{{!master(layout/_master.tmpl)}} +

                                                                                                                                                                                                                                                                                      {{title}}

                                                                                                                                                                                                                                                                                      +{{#items.Length}} +
                                                                                                                                                                                                                                                                                      +{{#items}} +
                                                                                                                                                                                                                                                                                      + {{name}} +
                                                                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                                                                      {{name}}
                                                                                                                                                                                                                                                                                      +

                                                                                                                                                                                                                                                                                      {{{description}}}

                                                                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                                                                      + {{#usage}} +
                                                                                                                                                                                                                                                                                      + {{#config}}
                                                                                                                                                                                                                                                                                      docfx.json: {{config}}
                                                                                                                                                                                                                                                                                      {{/config}} + {{#command}}
                                                                                                                                                                                                                                                                                      docfx: {{command}}
                                                                                                                                                                                                                                                                                      {{/command}} + {{#init}}
                                                                                                                                                                                                                                                                                      docfx init: {{init}}
                                                                                                                                                                                                                                                                                      {{/init}} +
                                                                                                                                                                                                                                                                                      + {{/usage}} +
                                                                                                                                                                                                                                                                                      +
                                                                                                                                                                                                                                                                                      +{{/items}} +
                                                                                                                                                                                                                                                                                      +{{/items.Length}} + + diff --git a/docs/template/public/main.css b/docs/template/public/main.css new file mode 100644 index 00000000..b0b8c1fd --- /dev/null +++ b/docs/template/public/main.css @@ -0,0 +1,10 @@ +/** + * Licensed to the .NET Foundation under one or more agreements. + * The .NET Foundation licenses this file to you under the MIT license. + */ + +/* Checkout https://getbootstrap.com/docs/5.3/customize/color/ for more customization options */ +body { + --bs-link-color-rgb: 66, 184, 131 !important; + --bs-link-hover-color-rgb: 64, 180, 128 !important; +} diff --git a/docs/template/public/main.js b/docs/template/public/main.js new file mode 100644 index 00000000..d5c4867a --- /dev/null +++ b/docs/template/public/main.js @@ -0,0 +1,14 @@ +/** + * Licensed to the .NET Foundation under one or more agreements. + * The .NET Foundation licenses this file to you under the MIT license. + */ + +export default { + iconLinks: [ + { + icon: 'github', + href: 'https://github.com/dotnet/docfx', + title: 'GitHub' + } + ] +} diff --git a/docs/template/schemas/Dashboard.schema.json b/docs/template/schemas/Dashboard.schema.json new file mode 100644 index 00000000..a00ab759 --- /dev/null +++ b/docs/template/schemas/Dashboard.schema.json @@ -0,0 +1,45 @@ +{ + "title": "Dashboard", + "$schema": "https://dotnet.github.io/docfx/schemas/v1.0/schema.json#", + "version": "1.0.0", + "description": "Schema for dashboard", + "id": "https://github.com/dotnet/docfx/schemas/Dashboard.schema.json", + "type": "object", + "properties": { + "uid": { + "type": "string", + "contentType": "uid" + }, + "title": { + "type": "string", + "tags": [ + "localizable" + ] + }, + "description": { + "type": "string", + "contentType": "markdown", + "tags": [ + "localizable" + ] + }, + "items": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "contentType": "markdown", + "tags": [ + "localizable" + ] + } + }, + "type": "object" + }, + "type": "array" + } + } +} \ No newline at end of file diff --git a/docs/toc.yml b/docs/toc.yml new file mode 100644 index 00000000..ddd7221d --- /dev/null +++ b/docs/toc.yml @@ -0,0 +1,8 @@ +ο»Ώ- name: Home + href: index.md +- name: API Documentation + href: api/WebExpress.WebUI.html +- name: User Guide + href: user-guide.md +- name: Tutorials + href: tutorials.md diff --git a/docs/tutorials.md b/docs/tutorials.md new file mode 100644 index 00000000..81058e51 --- /dev/null +++ b/docs/tutorials.md @@ -0,0 +1,17 @@ +![WebExpress](https://raw.githubusercontent.com/ReneSchwarzer/WebExpress/main/assets/banner.png) + +# Tutorials +Welcome to the `WebExpress` Tutorials! Here, you'll find step-by-step guides and helpful resources to get the most out +of `WebExpress`. Whether you're a beginner just starting out or an experienced developer looking to expand your skills, +our tutorials offer something for everyone. + +# Getting Started +Begin with our basic tutorial: + +- [HelloWorld](https://github.com/ReneSchwarzer/WebExpress.Tutorial.HelloWorld#readme) +- [WebApp](https://github.com/ReneSchwarzer/WebExpress.Tutorial.WebApp#readme) + +This tutorial will guide you through the initial steps of creating and running your first `WebExpress` application. + +Stay tuned for more exciting and educational tutorials to help you unlock the full potential of `WebExpress`. Happy coding and +best of luck with your projects! diff --git a/docs/user-guide.md b/docs/user-guide.md new file mode 100644 index 00000000..74880728 --- /dev/null +++ b/docs/user-guide.md @@ -0,0 +1,15 @@ +![WebExpress](https://raw.githubusercontent.com/ReneSchwarzer/WebExpress/main/assets/banner.png) + +# User guide +Welcome to the `WebExpress.WebUI` User Guide. This guide will help you get started with `WebExpress.WebUI` and make the most out of its +features. Follow the links below to begin your journey. + +# Getting started +To get started with `WebExpress.WebUI`, use the following guides: + +- [Installation Guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/installation_guide.md) +- [Development Guide](https://github.com/ReneSchwarzer/WebExpress/blob/main/doc/development_guide.md) +- [WebExpress.WebCore API Documentation](https://reneschwarzer.github.io/WebExpress.WebCore/) +- [WebExpress.WebUI API Documentation](https://reneschwarzer.github.io/WebExpress.WebUI/) + +We hope you enjoy using `WebExpress.WebUI` and find it valuable for your projects. Happy coding! From 22357f839458676f4d060e4e4cd9ea548000be8d Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 29 Dec 2024 14:29:35 +0100 Subject: [PATCH 36/59] chore: generate API documentation in main branch --- .github/workflows/generate-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml index 23b23923..e427ab22 100644 --- a/.github/workflows/generate-docs.yml +++ b/.github/workflows/generate-docs.yml @@ -3,7 +3,7 @@ name: Generate and Deploy Documentation on: push: branches: - - develop + - main permissions: actions: read From 45fe91739407e8d20ce31131a925a85ccbeb0d3e Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sun, 29 Dec 2024 21:32:34 +0100 Subject: [PATCH 37/59] fix: bug fixes and refactoring --- src/WebExpress.WebUI.Test/TestPage.cs | 2 +- .../WebPage/UnitTestPageManager.cs | 1 + .../WebStemap/UnitTestSitemapManager.cs | 37 +++++++++++++++++++ .../WebPage/VisualTreeControl.cs | 34 ++++++++--------- 4 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebStemap/UnitTestSitemapManager.cs diff --git a/src/WebExpress.WebUI.Test/TestPage.cs b/src/WebExpress.WebUI.Test/TestPage.cs index a1e3ee69..c1b29e1d 100644 --- a/src/WebExpress.WebUI.Test/TestPage.cs +++ b/src/WebExpress.WebUI.Test/TestPage.cs @@ -9,7 +9,7 @@ namespace WebExpress.WebUI.Test /// A dummy class for testing purposes. ///
                                                                                                                                                                                                                                                                                      [Title("webindex:pagea.label")] - [Segment("pagea", "webindex:homepage.label")] + [Segment("page", "webindex:homepage.label")] [ContextPath(null)] public sealed class TestPage : IPage { diff --git a/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs b/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs index 48e5b42a..b1382f95 100644 --- a/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs +++ b/src/WebExpress.WebUI.Test/WebPage/UnitTestPageManager.cs @@ -30,5 +30,6 @@ public void Id(Type applicationType, Type pageType, string id) Assert.Contains(id, page.Select(x => x.EndpointId?.ToString())); } + } } diff --git a/src/WebExpress.WebUI.Test/WebStemap/UnitTestSitemapManager.cs b/src/WebExpress.WebUI.Test/WebStemap/UnitTestSitemapManager.cs new file mode 100644 index 00000000..55e72cb8 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebStemap/UnitTestSitemapManager.cs @@ -0,0 +1,37 @@ +ο»Ώusing WebExpress.WebCore.WebSitemap; +using WebExpress.WebUI.Test.Fixture; + +namespace WebExpress.WebUI.Test.WebStemap +{ + /// + /// Test the sitemap manager. + /// + [Collection("NonParallelTests")] + public class UnitTestSitemapManager + { + /// + /// Test the SearchResource function of the sitemap. + /// + [Theory] + [InlineData("http://localhost:8080/server/app/page", "webexpress.webui.test.testpage")] + public void SearchResource(string uri, string id) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var context = UnitTestControlFixture.CreateHttpContextMock(); + var httpServerContext = UnitTestControlFixture.CreateHttpServerContextMock(); + var searchContext = Activator.CreateInstance(); + componentHub.SitemapManager.Refresh(); + typeof(SearchContext).GetProperty("HttpServerContext").SetValue(searchContext, httpServerContext); + typeof(SearchContext).GetProperty("Culture").SetValue(searchContext, httpServerContext.Culture); + typeof(SearchContext).GetProperty("HttpContext").SetValue(searchContext, context); + + // test execution + var searchResult = componentHub.SitemapManager.SearchResource(new Uri(uri), searchContext); + + var response = componentHub.EndpointManager.HandleRequest(UnitTestControlFixture.CrerateRequestMock(), searchResult.EndpointContext); + + Assert.Equal(id, searchResult?.EndpointContext?.EndpointId.ToString()); + } + } +} diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index 433c5622..ba0ed06e 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -91,7 +91,7 @@ public VisualTreeControl(IComponentHub componentHub, IPageContext pageContext) Title = pageContext?.PageTitle; - var contextPath = pageContext.ContextPath; + var contextPath = pageContext.ApplicationContext?.ContextPath; _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/fontawesome.min.css")); _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/bootstrap.min.css")); _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/solid.css")); @@ -109,21 +109,21 @@ public VisualTreeControl(IComponentHub componentHub, IPageContext pageContext) _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.table.css")); _cssLinks.Add(UriResource.Combine(contextPath, "/assets/css/webexpress.webui.toolpanel.css")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); - _headerScripts.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/jquery-3.7.1.min.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/popper.min.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/bootstrap.min.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/summernote-bs5.min.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.expand.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.form.progress.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalform.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.modalpage.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.more.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.move.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.pagination.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.search.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.selection.js")); + _headerScriptLinks.Add(UriResource.Combine(contextPath, "/assets/js/webexpress.webui.table.js")); _meta.Add("charset", "UTF-8"); _meta.Add("viewport", "width=device-width, initial-scale=1"); @@ -315,7 +315,5 @@ public virtual IHtmlNode Render(IVisualTreeContext context) return html; } - - } } From 8433af444f55bd9149eea72d61d3b31487d50771 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Sat, 4 Jan 2025 16:12:50 +0100 Subject: [PATCH 38/59] changed render call parameters to support visualtree in controls --- .../TestFragmentControlForm.cs | 23 +++ .../TestSectionFragmentControlForm.cs | 11 ++ .../WebControl/UnitTestControlAlert.cs | 7 +- .../WebControl/UnitTestControlAttribute.cs | 31 ++-- .../WebControl/UnitTestControlAvatar.cs | 26 ++- .../WebControl/UnitTestControlBadge.cs | 31 ++-- .../WebControl/UnitTestControlBreadcrumb.cs | 79 ++++++-- .../WebControl/UnitTestControlButton.cs | 51 ++--- .../WebControl/UnitTestControlButtonLink.cs | 50 +++-- .../WebControl/UnitTestControlCanvas.cs | 21 ++- .../WebControl/UnitTestControlCardCounter.cs | 36 ++-- .../WebControl/UnitTestControlCarousel.cs | 21 ++- .../WebControl/UnitTestControlChart.cs | 56 +++--- .../WebControl/UnitTestControlDropdown.cs | 66 ++++--- .../UnitTestControlDropdownItemDivider.cs | 6 +- .../UnitTestControlDropdownItemHeader.cs | 11 +- .../UnitTestControlDropdownItemLink.cs | 51 ++--- .../WebControl/UnitTestControlForm.cs | 134 +++----------- .../WebControl/UnitTestControlFormInline.cs | 10 +- .../UnitTestControlFormItemButton.cs | 56 +++--- .../UnitTestControlFormItemButtonSubmit.cs | 56 +++--- ...estControlFormItemGroupColumnHorizontal.cs | 11 +- .../UnitTestControlFormItemGroupColumnMix.cs | 11 +- ...tTestControlFormItemGroupColumnVertical.cs | 11 +- .../UnitTestControlFormItemGroupHorizontal.cs | 11 +- .../UnitTestControlFormItemGroupMix.cs | 11 +- .../UnitTestControlFormItemGroupVertical.cs | 11 +- .../UnitTestControlFormItemHelpText.cs | 16 +- .../UnitTestControlFormItemInputCheckbox.cs | 21 ++- .../UnitTestControlFormItemInputCombobox.cs | 41 +++-- .../UnitTestControlFormItemInputDatepicker.cs | 21 ++- .../UnitTestControlFormItemInputFile.cs | 21 ++- .../UnitTestControlFormItemInputGroup.cs | 16 +- .../UnitTestControlFormItemInputHidden.cs | 16 +- .../UnitTestControlFormItemInputMove.cs | 21 ++- .../UnitTestControlFormItemInputRadio.cs | 21 ++- .../UnitTestControlFormItemInputSelection.cs | 36 ++-- .../UnitTestControlFormItemInputTextBox.cs | 56 +++--- .../UnitTestControlFormItemLabel.cs | 21 ++- .../UnitTestControlFormItemPanel.cs | 21 ++- .../UnitTestControlFormItemPrepend.cs | 21 ++- .../UnitTestControlFormItemStaticText.cs | 21 ++- .../WebControl/UnitTestControlHtml.cs | 11 +- .../WebControl/UnitTestControlIcon.cs | 26 ++- .../WebControl/UnitTestControlImage.cs | 26 ++- .../WebControl/UnitTestControlLine.cs | 11 +- .../WebControl/UnitTestControlLink.cs | 51 ++--- .../WebControl/UnitTestControlLinkList.cs | 31 ++-- .../WebControl/UnitTestControlList.cs | 21 ++- .../UnitTestControlListItemButton.cs | 26 +-- .../WebControl/UnitTestControlListItemLink.cs | 56 +++--- .../WebControl/UnitTestControlModal.cs | 11 +- .../WebControl/UnitTestControlModalForm.cs | 16 +- .../UnitTestControlMultipleProgressBar.cs | 31 ++-- .../WebControl/UnitTestControlNavigation.cs | 21 ++- .../UnitTestControlNavigationItemDropdown.cs | 66 ++++--- .../UnitTestControlNavigationItemHeader.cs | 11 +- .../UnitTestControlNavigationItemLink.cs | 50 +++-- .../WebControl/UnitTestControlPanel.cs | 26 ++- .../WebControl/UnitTestControlPanelCallout.cs | 21 ++- .../WebControl/UnitTestControlPanelCard.cs | 31 ++-- .../WebControl/UnitTestControlPanelCenter.cs | 26 ++- .../WebControl/UnitTestControlPanelFlexbox.cs | 41 +++-- .../WebControl/UnitTestControlPanelFooter.cs | 21 ++- .../WebControl/UnitTestControlPanelGrid.cs | 26 ++- .../WebControl/UnitTestControlPanelHeader.cs | 31 ++-- .../WebControl/UnitTestControlPanelMain.cs | 21 ++- .../WebControl/UnitTestControlPanelMedia.cs | 46 +++-- .../WebControl/UnitTestControlPanelNavbar.cs | 26 ++- .../WebControl/UnitTestControlPanelSplit.cs | 21 ++- .../WebControl/UnitTestControlPanelToast.cs | 26 ++- .../WebControl/UnitTestControlPanelTool.cs | 26 ++- .../WebControl/UnitTestControlProgressBar.cs | 46 +++-- .../WebControl/UnitTestControlSplitButton.cs | 51 ++--- .../UnitTestControlSplitButtonItemDivider.cs | 6 +- .../UnitTestControlSplitButtonItemHeader.cs | 11 +- .../UnitTestControlSplitButtonItemLink.cs | 51 ++--- .../UnitTestControlSplitButtonLink.cs | 51 ++--- .../WebControl/UnitTestControlTable.cs | 26 ++- .../WebControl/UnitTestControlTableColumn.cs | 21 ++- .../WebControl/UnitTestControlTableRow.cs | 16 +- .../WebControl/UnitTestControlTag.cs | 21 ++- .../WebControl/UnitTestControlText.cs | 16 +- .../UnitTestControlToolBarItemSeperator.cs | 6 +- .../WebControl/UnitTestControlToolbar.cs | 16 +- .../UnitTestControlToolbarItemButton.cs | 61 +++--- .../WebControl/UnitTestControlTree.cs | 21 ++- .../WebControl/UnitTestControlTreeItem.cs | 31 ++-- .../WebControl/UnitTestControlTreeItemLink.cs | 51 ++--- .../WebFragment/UnitTestFragmentManager.cs | 5 +- src/WebExpress.WebUI/WebControl/Control.cs | 3 +- .../WebControl/ControlArlert.cs | 3 +- .../WebControl/ControlAttribute.cs | 3 +- .../WebControl/ControlAvatar.cs | 5 +- .../WebControl/ControlBadge.cs | 3 +- .../WebControl/ControlBreadcrumb.cs | 72 +++----- .../WebControl/ControlButton.cs | 9 +- .../WebControl/ControlButtonLink.cs | 9 +- .../WebControl/ControlCanvas.cs | 3 +- .../WebControl/ControlCardCounter.cs | 9 +- .../WebControl/ControlCarousel.cs | 5 +- .../WebControl/ControlChart.cs | 15 +- .../WebControl/ControlDropdown.cs | 11 +- .../WebControl/ControlDropdownItemDivider.cs | 3 +- .../WebControl/ControlDropdownItemHeader.cs | 3 +- .../WebControl/ControlDropdownItemLink.cs | 7 +- .../WebControl/ControlForm.cs | 22 ++- .../WebControl/ControlFormItem.cs | 8 +- .../WebControl/ControlFormItemButton.cs | 8 +- .../WebControl/ControlFormItemGroupColumn.cs | 14 +- .../ControlFormItemGroupColumnHorizontal.cs | 14 +- .../ControlFormItemGroupColumnMix.cs | 14 +- .../ControlFormItemGroupColumnVertical.cs | 14 +- .../ControlFormItemGroupHorizontal.cs | 14 +- .../WebControl/ControlFormItemGroupMix.cs | 14 +- .../ControlFormItemGroupVertical.cs | 14 +- .../WebControl/ControlFormItemHelpText.cs | 4 +- .../ControlFormItemInputCheckbox.cs | 4 +- .../ControlFormItemInputCombobox.cs | 4 +- .../ControlFormItemInputDatepicker.cs | 4 +- .../WebControl/ControlFormItemInputFile.cs | 4 +- .../WebControl/ControlFormItemInputGroup.cs | 6 +- .../WebControl/ControlFormItemInputHidden.cs | 4 +- .../WebControl/ControlFormItemInputMove.cs | 6 +- .../WebControl/ControlFormItemInputRadio.cs | 4 +- .../ControlFormItemInputSelection.cs | 6 +- .../WebControl/ControlFormItemInputTextBox.cs | 6 +- .../WebControl/ControlFormItemLabel.cs | 4 +- .../WebControl/ControlFormItemPanel.cs | 6 +- .../WebControl/ControlFormItemPrepend.cs | 6 +- .../WebControl/ControlFormItemStaticText.cs | 4 +- .../WebControl/ControlHtml.cs | 3 +- .../WebControl/ControlIcon.cs | 3 +- .../WebControl/ControlImage.cs | 3 +- .../WebControl/ControlLine.cs | 3 +- .../WebControl/ControlLink.cs | 9 +- .../WebControl/ControlLinkList.cs | 5 +- .../WebControl/ControlList.cs | 12 +- .../WebControl/ControlListItem.cs | 5 +- .../WebControl/ControlListItemButton.cs | 5 +- .../WebControl/ControlListItemLink.cs | 7 +- .../WebControl/ControlModal.cs | 11 +- .../WebControl/ControlModalForm.cs | 20 +- .../WebControl/ControlMultipleProgressBar.cs | 3 +- .../WebControl/ControlNavigation.cs | 5 +- .../ControlNavigationItemDropdown.cs | 5 +- .../WebControl/ControlNavigationItemHeader.cs | 3 +- .../WebControl/ControlNavigationItemLink.cs | 5 +- .../WebControl/ControlPagination.cs | 1 + .../WebControl/ControlPanel.cs | 5 +- .../WebControl/ControlPanelCallout.cs | 5 +- .../WebControl/ControlPanelCard.cs | 5 +- .../WebControl/ControlPanelCenter.cs | 5 +- .../WebControl/ControlPanelFlexbox.cs | 5 +- .../WebControl/ControlPanelFooter.cs | 5 +- .../WebControl/ControlPanelGrid.cs | 5 +- .../WebControl/ControlPanelHeader.cs | 5 +- .../WebControl/ControlPanelMain.cs | 5 +- .../WebControl/ControlPanelMedia.cs | 5 +- .../WebControl/ControlPanelNavbar.cs | 5 +- .../WebControl/ControlPanelSplit.cs | 16 +- .../WebControl/ControlPanelTool.cs | 7 +- .../WebControl/ControlProgressBar.cs | 3 +- .../WebControl/ControlSplitButton.cs | 11 +- .../ControlSplitButtonItemDivider.cs | 3 +- .../ControlSplitButtonItemHeader.cs | 3 +- .../WebControl/ControlSplitButtonItemLink.cs | 5 +- .../WebControl/ControlSplitButtonLink.cs | 11 +- .../WebControl/ControlTable.cs | 7 +- .../WebControl/ControlTableColumn.cs | 5 +- .../WebControl/ControlTableRow.cs | 5 +- src/WebExpress.WebUI/WebControl/ControlTag.cs | 7 +- .../WebControl/ControlTagCloud.cs | 1 + .../WebControl/ControlText.cs | 3 +- .../WebControl/ControlTimeline.cs | 1 + .../WebControl/ControlTimelineComment.cs | 1 + .../WebControl/ControlTimelineItem.cs | 1 + .../WebControl/ControlToolbar.cs | 7 +- .../WebControl/ControlTree.cs | 7 +- .../WebControl/ControlTreeItem.cs | 7 +- .../WebControl/ControlTreeItemLink.cs | 9 +- src/WebExpress.WebUI/WebControl/IControl.cs | 3 +- .../WebFragment/FragmentControlForm.cs | 35 ++++ .../WebFragment/IFragmentControl.cs | 7 +- .../WebPage/IRenderControlContext.cs | 12 -- .../WebPage/IVisualTreeControl.cs | 174 ++++++++++++++++++ .../WebPage/RenderControlContext.cs | 17 -- .../WebPage/VisualTreeControl.cs | 7 +- 188 files changed, 2162 insertions(+), 1377 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/TestFragmentControlForm.cs create mode 100644 src/WebExpress.WebUI.Test/TestSectionFragmentControlForm.cs create mode 100644 src/WebExpress.WebUI/WebFragment/FragmentControlForm.cs create mode 100644 src/WebExpress.WebUI/WebPage/IVisualTreeControl.cs diff --git a/src/WebExpress.WebUI.Test/TestFragmentControlForm.cs b/src/WebExpress.WebUI.Test/TestFragmentControlForm.cs new file mode 100644 index 00000000..6ffeb33c --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestFragmentControlForm.cs @@ -0,0 +1,23 @@ +ο»Ώusing WebExpress.WebCore.WebAttribute; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebFragment; + +namespace WebExpress.WebUI.Test +{ + /// + /// A dummy fragment for testing purposes. + /// + [Section()] + public sealed class TestFragmentControlForm : FragmentControlModalForm + { + /// + /// Initializes a new instance of the class. + /// + public TestFragmentControlForm(IFragmentContext fragmentContext) + : base(fragmentContext) + { + Add(new ControlText() { Text = "FragmentControlForm" }); + } + } +} diff --git a/src/WebExpress.WebUI.Test/TestSectionFragmentControlForm.cs b/src/WebExpress.WebUI.Test/TestSectionFragmentControlForm.cs new file mode 100644 index 00000000..c57d42fa --- /dev/null +++ b/src/WebExpress.WebUI.Test/TestSectionFragmentControlForm.cs @@ -0,0 +1,11 @@ +ο»Ώusing WebExpress.WebCore.WebSection; + +namespace WebExpress.WebUI.Test +{ + /// + /// Represents a test section for testing in the web UI. + /// + internal class TestSectionFragmentControlForm : ISection + { + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs index aa8c8566..3f863a4d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAlert.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -21,12 +22,13 @@ public void Id(string id, string expected) // preconditions var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAlert(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -41,13 +43,14 @@ public void Text(string text, string expected) // preconditions var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAlert() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs index 7eaf0d91..da3ea0fe 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAttribute.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlAttribute public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Name(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { Name = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -62,15 +65,16 @@ public void Name(string title, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -92,15 +96,16 @@ public void Icon(TypeIcon icon, string expected) public void NameColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { NameColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -114,15 +119,16 @@ public void NameColor(TypeColorText color, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -136,15 +142,16 @@ public void Value(string value, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { Uri = uri != null ? new Uri(uri) : null }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs index 9fd257e5..89bf9b44 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlAvatar.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlAvatar public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAvatar(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void User(string user, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAvatar() { User = user }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -61,15 +64,16 @@ public void User(string user, string expected) public void Image(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAvatar() { Image = uri != null ? new Uri(uri) : null }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,15 +95,16 @@ public void Image(string uri, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAvatar() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -119,15 +124,16 @@ public void TextColor(TypeColorText color, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAvatar() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs index 2523e09d..740f71ac 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBadge.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlBadge public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Value(int? value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,15 +66,16 @@ public void Value(int? value, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge() { Uri = uri != null ? new Uri(uri) : null }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Uri(string uri, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -121,15 +126,16 @@ public void TextColor(TypeColorText color, string expected) public void BackgroundColor(TypeColorBackgroundBadge backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge() { BackgroundColor = new PropertyColorBackgroundBadge(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -143,15 +149,16 @@ public void BackgroundColor(TypeColorBackgroundBadge backgroundColor, string exp public void Pill(TypePillBadge pill, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBadge() { Pill = pill }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs index 2ce72d3e..ff6ee8a1 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlBreadcrumb.cs @@ -1,5 +1,7 @@ -ο»Ώusing WebExpress.WebUI.Test.Fixture; +ο»Ώusing WebExpress.WebCore.WebUri; +using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +20,15 @@ public class UnitTestControlBreadcrumb public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlBreadcrumb(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,12 +42,13 @@ public void Id(string id, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); - var control = new ControlBreadcrumb { Uri = uri }; + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlBreadcrumb { Uri = new UriResource(uri) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -58,12 +62,13 @@ public void Uri(string uri, string expected) public void EmptyName(string emptyName, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); - var control = new ControlBreadcrumb { EmptyName = emptyName }; + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlBreadcrumb { EmptyName = emptyName, Uri = new UriResource("http://example.com") }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -78,12 +83,13 @@ public void EmptyName(string emptyName, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); - var control = new ControlBreadcrumb { Size = size }; + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlBreadcrumb { Size = size, Uri = new UriResource("http://example.com") }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,16 +99,17 @@ public void Size(TypeSizeButton size, string expected) ///
                                                                                                                                                                                                                                                                                      [Theory] [InlineData(null, @"
                                                                                                                                                                                                                                                                                        ")] - [InlineData("Prefix", @"
                                                                                                                                                                                                                                                                                          ")] + [InlineData("Prefix", @"
                                                                                                                                                                                                                                                                                          1. Prefix
                                                                                                                                                                                                                                                                                          ")] public void Prefix(string prefix, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); - var control = new ControlBreadcrumb { Prefix = prefix }; + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlBreadcrumb { Prefix = prefix, Uri = new UriResource("http://example.com") }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,12 +123,46 @@ public void Prefix(string prefix, string expected) public void TakeLast(ushort takeLast, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); - var control = new ControlBreadcrumb { TakeLast = takeLast }; + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlBreadcrumb { TakeLast = takeLast, Uri = new UriResource("http://example.com") }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the render function of the breadcrumb control. + /// + [Theory] + [InlineData(null, @"
                                                                                                                                                                                                                                                                                            ")] + [InlineData("http://localhost:80/app/page", @"
                                                                                                                                                                                                                                                                                            1. abc
                                                                                                                                                                                                                                                                                            ")] + public void Render(string uri, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var application = componentHub.ApplicationManager.GetApplications(typeof(TestApplication)).FirstOrDefault(); + var context = UnitTestControlFixture.CrerateRenderContextMock(application); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var uriResource = new UriResource(uri); + var control = new ControlBreadcrumb() + { + Uri = uriResource + }; + + if (uriResource.PathSegments.LastOrDefault() != null) + { + uriResource.PathSegments.LastOrDefault().Display ??= "abc"; + } + + var uriProperty = context.Request.GetType().GetProperty("Uri"); + uriProperty.SetValue(context.Request, uriResource); + + // test execution + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs index e764bd06..28b35cac 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButton.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlButton public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -62,15 +65,16 @@ public void Text(string text, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { BackgroundColor = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -115,8 +120,9 @@ public void BackgroundColor(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { Outline = outline, @@ -124,7 +130,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -138,15 +144,16 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -160,15 +167,16 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButton() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -180,8 +188,9 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -194,12 +203,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); - var html4 = control1.Render(context); - var html5 = control2.Render(context); - var html6 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs index a7286326..cd397044 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlButtonLink.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlButtonLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -63,15 +66,16 @@ public void Text(string text, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -86,15 +90,16 @@ public void Tooltip(string tooltip, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -112,15 +117,16 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { BackgroundColor = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -139,8 +145,9 @@ public void BackgroundColor(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Outline = outline, @@ -148,7 +155,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -162,15 +169,16 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -184,15 +192,16 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlButtonLink() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -204,16 +213,17 @@ public void Icon(TypeIcon icon, string expected) public void Content() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlButtonLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlButtonLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlButtonLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); // test execution - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs index ad093506..4ad9bb3f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCanvas.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlCanvas public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCanvas(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCanvas() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Width(TypeWidth width, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCanvas() { Width = width, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -95,15 +99,16 @@ public void Width(TypeWidth width, string expected) public void Height(TypeHeight height, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCanvas() { Height = height, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs index 5b3cb0fa..115d4c32 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCardCounter.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlCardCounter public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Value(int? value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { Value = value, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -87,15 +91,16 @@ public void Value(int? value, string expected) public void Progress(uint? value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { Progress = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -109,15 +114,16 @@ public void Progress(uint? value, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -139,15 +145,16 @@ public void Icon(TypeIcon icon, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -167,15 +174,16 @@ public void TextColor(TypeColorText color, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCardCounter() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs index 412eacfd..e8043bfd 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlCarousel.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlCarousel public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCarousel(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -47,15 +49,16 @@ public void Id(string id, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCarousel() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -75,15 +78,16 @@ public void TextColor(TypeColorText color, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlCarousel() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -98,8 +102,9 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var item = new ControlCarouselItem(childInstance); var control = new ControlCarousel(); @@ -107,7 +112,7 @@ public void Add(Type child, string expected) // test execution control.Add(item); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs index 03f90445..3c01440b 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlChart.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlChart public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -47,15 +49,16 @@ public void Id(string id, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -75,15 +78,16 @@ public void TextColor(TypeColorText color, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -97,15 +101,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Type(TypeChart type, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Type = type }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -119,15 +124,16 @@ public void Type(TypeChart type, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Title = title }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -141,15 +147,16 @@ public void Title(string title, string expected) public void TitleX(string titleX, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { TitleX = titleX }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -163,15 +170,16 @@ public void TitleX(string titleX, string expected) public void TitleY(string titleY, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { TitleY = titleY }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -185,15 +193,16 @@ public void TitleY(string titleY, string expected) public void Width(int width, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Width = width }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -207,15 +216,16 @@ public void Width(int width, string expected) public void Height(int height, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Height = height }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -229,15 +239,16 @@ public void Height(int height, string expected) public void Minimum(float minimum, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Minimum = minimum }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -251,15 +262,16 @@ public void Minimum(float minimum, string expected) public void Maximum(float maximum, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlChart() { Maximum = maximum }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs index 71f550fe..f19b7b55 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdown.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlDropdown public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorButton backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { BackgroundColor = new PropertyColorButton(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -68,15 +71,16 @@ public void BackgroundColor(TypeColorButton backgroundColor, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -90,8 +94,9 @@ public void Size(TypeSizeButton size, string expected) public void Outline(bool outline, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Outline = outline, @@ -99,7 +104,7 @@ public void Outline(bool outline, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -113,15 +118,16 @@ public void Outline(bool outline, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -135,15 +141,16 @@ public void Block(TypeBlockButton block, string expected) public void Toogle(TypeToggleDropdown toogle, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Toogle = toogle }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -158,15 +165,16 @@ public void Toogle(TypeToggleDropdown toogle, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -181,15 +189,16 @@ public void Text(string text, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Tooltip = tooltip, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -204,15 +213,16 @@ public void Tooltip(string tooltip, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Value = value, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -226,15 +236,16 @@ public void Value(string value, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -249,15 +260,16 @@ public void Icon(TypeIcon icon, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -271,15 +283,16 @@ public void Active(TypeActive active, string expected) public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown() { AlignmentMenu = alignmentMenu }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -291,14 +304,15 @@ public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expect public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdown(); // test execution control.Add(new ControlDropdownItemLink() { Text = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs index 1cb96b9d..9d206d54 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemDivider.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlDropdownItemDivider public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemDivider(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs index 1346a793..f6113cad 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemHeader.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlDropdownItemHeader public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemHeader(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemHeader() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs index 5e82365e..d7327ebe 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlDropdownItemLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlDropdownItemLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -156,15 +163,16 @@ public void Tooltip(string tooltip, string expected) public void Icon() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlDropdownItemLink() { Icon = new PropertyIcon(TypeIcon.Star) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } @@ -176,8 +184,9 @@ public void Icon() public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlDropdownItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlDropdownItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlDropdownItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -190,12 +199,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs index 5468e22f..b2a5d7dc 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlForm.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlForm public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -46,15 +48,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm() { BackgroundColor = new PropertyColorBackground(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -68,16 +71,17 @@ public void BackgroundColor(TypeColorBackground color, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,16 +95,17 @@ public void Name(string name, string expected) public void FormLayout(TypeLayoutForm formLayout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm() { FormLayout = formLayout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -115,16 +120,17 @@ public void FormLayout(TypeLayoutForm formLayout, string expected) public void ItemLayout(TypeLayoutFormItem itemLayout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm() { ItemLayout = itemLayout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -136,11 +142,13 @@ public void ItemLayout(TypeLayoutFormItem itemLayout, string expected) public void EmptyForm() { // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlForm(); - var html = control.Render(context); + var html = control.Render(context, visualTree); // test execution AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                            - /// Tests a simple form with id. - ///
                                                                                                                                                                                                                                                                                            - [Fact] - public void EmptyFormWithId() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlForm("form"); - - //var html = control.Render(context); - - //// test execution - //Assert.StartsWith(@" - /// Tests a simple form. - /// The control elements are added during rendering. - ///
                                                                                                                                                                                                                                                                                            - [Fact] - public void SimpleFormAtRender() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var control = new ControlForm(); - //var item = new ControlFormItemInputTextBox() { }; - - //// test execution - //var html = control.Render(context, [item]); - - //Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added when instantiating. - /// - [Fact] - public void SimpleFormAtInstancing() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var item = new ControlFormItemInputTextBox() { }; - //var control = new ControlForm("form", item); - - //// test execution - //var html = control.Render(context); - - //Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a simple form. - /// The control elements are added using add. - /// - [Fact] - public void SimpleFormAtAdd() - { - //// preconditions - //var context = Fixture.CrerateContext(); - //var item = new ControlFormItemInputTextBox() { }; - //var control = new ControlForm("form"); - - //control.Add(item); - - //// test execution - //var html = control.Render(context); - //var str = html.ToString(); - - //Assert.Contains(@"", html.Trim()); - } - - /// - /// Tests a complex form. - /// - [Fact] - public void ComplexForm() - { - //// preconditions - //var expectedResult = Fixture.GetEmbeddedResource("ComplexForm.txt"); - //var context = Fixture.CrerateContext(); - //var item1 = new ControlFormItemInputTextBox() { Label = "Label1", Help = "Help1", Placeholder = "Placeholder1" }; - //var item2 = new ControlFormItemInputTextBox() { Label = "Label2", Help = "Help2", Placeholder = "Placeholder2" }; - //var submitButton = new ControlFormItemButtonSubmit("Submit"); - //var control = new ControlForm("form", item1, item2); - //control.AddPrimaryButton(submitButton); - - - //// test execution - //var html = control.Render(context); - //var str = html.ToString(); - - //// postconditions - //expectedResult = expectedResult.Replace("05c888e8-15f3-4be8-b765-0d7be63cc82b", control.FormId.Id); - //expectedResult = expectedResult.Replace("974c6159-98e3-4ede-8bb5-6bc4d52e1770", control.SubmitType.Id); - - //Assert.Equal(expectedResult.Trim(), str.Trim()); - } } } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs index 2592df98..cb231902 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormInline.cs @@ -40,7 +40,7 @@ public void EmptyForm() //var context = Fixture.CrerateContext(); //var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; - //var html = control.Render(context); + //var html = control.Render(context, visualTree); //var str = html.ToString(); //// test execution @@ -58,7 +58,7 @@ public void EmptyFormChangeSubmitText() //var control = new ControlForm() { FormLayout = TypeLayoutForm.Inline }; //control.AddPrimaryButton(new ControlFormItemButtonSubmit("") { Text = "sendbutton" }); - //var html = control.Render(context); + //var html = control.Render(context, visualTree); //var str = html.ToString(); //// test execution @@ -75,7 +75,7 @@ public void EmptyFormWithId() //var context = Fixture.CrerateContext(); //var control = new ControlForm("form") { FormLayout = TypeLayoutForm.Inline }; - //var html = control.Render(context); + //var html = control.Render(context, visualTree); //// test execution //Assert.StartsWith(@"", html.Trim()); } @@ -132,7 +132,7 @@ public void SimpleFormAtAdd() //control.Add(item); //// test execution - //var html = control.Render(context); + //var html = control.Render(context, visualTree); //var str = html.ToString(); //Assert.Contains(@"", html.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs index 2e969b8b..89756ca7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButton.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemButton public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,16 +67,17 @@ public void Text(string text, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -94,16 +98,17 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorBackground color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { BackgroundColor = new PropertyColorBackground(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -122,16 +127,17 @@ public void BackgroundColor(TypeColorBackground color, string expected) public void Color(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Color = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -151,9 +157,10 @@ public void Color(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Outline = outline, @@ -161,7 +168,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -175,16 +182,17 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -198,16 +206,17 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButton() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -219,9 +228,10 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlFormItemButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlFormItemButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlFormItemButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -234,12 +244,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); - var html4 = control1.Render(context); - var html5 = control2.Render(context); - var html6 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs index a4e69a28..000493f7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemButtonSubmit public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,16 +67,17 @@ public void Text(string text, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -94,16 +98,17 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorBackground color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { BackgroundColor = new PropertyColorBackground(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -122,16 +127,17 @@ public void BackgroundColor(TypeColorBackground color, string expected) public void Color(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Color = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -151,9 +157,10 @@ public void Color(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Outline = outline, @@ -161,7 +168,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -175,16 +182,17 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -198,16 +206,17 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemButtonSubmit() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -219,9 +228,10 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlFormItemButtonSubmit(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlFormItemButtonSubmit(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlFormItemButtonSubmit(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -234,12 +244,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); - var html4 = control1.Render(context); - var html5 = control2.Render(context); - var html6 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs index 3ddb212c..28a74865 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnHorizontal.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupColumnHorizontal public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnHorizontal(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnHorizontal() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs index 4aa11fff..2bbec0f6 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnMix.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupColumnMix public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnMix(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnMix() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs index 303a50b0..605c26dd 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupColumnVertical.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupColumnVertical public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnVertical(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupColumnVertical() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs index 5b34df42..04c217a5 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupHorizontal.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupHorizontal public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupHorizontal(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupHorizontal() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs index 5c3bd618..eff1f3b8 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupMix.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupMix public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupMix(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupMix() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs index 0f1be537..89e3dfac 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemGroupVertical.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemGroupVertical public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupVertical(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemGroupVertical() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs index 5e8ae299..450e7dbc 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemHelpText.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemHelpText public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemHelpText(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,16 +43,17 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemHelpText() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -67,16 +70,17 @@ public void Text(string text, string expected) public void Size(TypeSizeText size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemHelpText() { Size = new PropertySizeText(size) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs index c2455ef0..86b3280d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCheckbox.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputCheckbox public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCheckbox(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Inline(bool inline, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCheckbox { Inline = inline }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Inline(bool inline, string expected) public void Description(string description, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCheckbox { Description = description }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Description(string description, string expected) public void Pattern(string pattern, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCheckbox { Pattern = pattern }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs index f314f105..5304b174 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputCombobox.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputCombobox public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Icon(TypeIcon icon, string expected) public void Label(string label, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox { Label = label }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Label(string label, string expected) public void Help(string help, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox { Help = help }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -109,16 +114,17 @@ public void Help(string help, string expected) public void Disabled(bool disabled, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox { Disabled = disabled }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -130,14 +136,15 @@ public void Disabled(bool disabled, string expected) public void Prepend() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox(); control.Prepend.Add(new ControlText { Text = "prepend" }); // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); var expected = @""; AssertExtensions.EqualWithPlaceholders(expected, html); @@ -150,14 +157,15 @@ public void Prepend() public void Append() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox(); control.Append.Add(new ControlText { Text = "append" }); // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); var expected = @""; AssertExtensions.EqualWithPlaceholders(expected, html); @@ -172,16 +180,17 @@ public void Append() public void Tag(object tag, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputCombobox { Tag = tag }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs index c039c8b1..92e3ae10 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputDatepicker.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputDatepicker public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputDatepicker(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputDatepicker() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputDatepicker() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Value(string value, string expected) public void Required(bool required, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputDatepicker() { Required = required }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs index 97731ebc..9b0c3f1c 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputFile.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputFile public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputFile(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputFile() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Required(bool required, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputFile() { Required = required }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,14 +90,15 @@ public void Required(bool required, string expected) public void Accept(string accept, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputFile(); // test execution control.AddAcceptFile(accept); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs index 837e6b71..b89e0892 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputGroup.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputGroup public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputGroup(id, new ControlFormItemGroupColumnVertical()) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputGroup(null, new ControlFormItemGroupColumnVertical()) { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputGroup(null, new ControlFormItemGroupColumnVertical()) { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs index 025b6d57..3371ab71 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputHidden.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputHidden public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputHidden(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputHidden() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputHidden() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs index 97aa977b..373307e7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputMove.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputMove public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputMove(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputMove() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputMove() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -84,16 +88,17 @@ public void Value(string value, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputMove() { }; // test execution control.Add(new ControlFormItemInputSelectionItem() { Label = "label" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.NotEmpty(control.Options); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                            ", html); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs index 3a8464fc..4a8a00fe 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputRadio.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputRadio public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputRadio(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Inline(bool inline, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputRadio { Inline = inline }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Inline(bool inline, string expected) public void Description(string description, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputRadio { Description = description }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Description(string description, string expected) public void Pattern(string pattern, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputRadio { Pattern = pattern }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs index b111d988..886c1b9d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputSelection.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputSelection public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Value(string value, string expected) public void Placeholder(string placeholder, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { Placeholder = placeholder }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -109,16 +114,17 @@ public void Placeholder(string placeholder, string expected) public void HideDescription(bool hideDescription, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { HideDescription = hideDescription }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -132,16 +138,17 @@ public void HideDescription(bool hideDescription, string expected) public void MultiSelect(bool multiSelect, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { MultiSelect = multiSelect }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -153,16 +160,17 @@ public void MultiSelect(bool multiSelect, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputSelection() { }; // test execution control.Add(new ControlFormItemInputSelectionItem() { Label = "label" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.NotEmpty(control.Options); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                            ", html); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs index 4a2997bb..fc459795 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemInputTextBox.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemInputTextBox public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,16 +67,17 @@ public void Name(string name, string expected) public void Format(TypesEditTextFormat format, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Format = format }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -87,16 +91,17 @@ public void Format(TypesEditTextFormat format, string expected) public void Description(string description, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Description = description }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -110,16 +115,17 @@ public void Description(string description, string expected) public void Placeholder(string placeholder, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Placeholder = placeholder }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -134,16 +140,17 @@ public void Placeholder(string placeholder, string expected) public void MinLength(uint? minLength, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { MinLength = minLength }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -158,16 +165,17 @@ public void MinLength(uint? minLength, string expected) public void MaxLength(uint? maxLength, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { MaxLength = maxLength }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -181,16 +189,17 @@ public void MaxLength(uint? maxLength, string expected) public void Required(bool required, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Required = required }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -204,16 +213,17 @@ public void Required(bool required, string expected) public void Pattern(string pattern, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Pattern = pattern }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -228,9 +238,10 @@ public void Pattern(string pattern, string expected) public void Rows(uint? rows, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Rows = rows, @@ -238,7 +249,7 @@ public void Rows(uint? rows, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -252,16 +263,17 @@ public void Rows(uint? rows, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemInputTextBox() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs index 765946b1..d1560fb0 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemLabel.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemLabel public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemLabel(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemLabel() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemLabel() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Text(string text, string expected) public void FormItem(bool formItem, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemLabel() { FormItem = formItem ? new ControlFormItemInputTextBox() : null }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs index a3fc56cb..f8894af6 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPanel.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemPanel public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPanel(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -43,16 +45,17 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPanel() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -67,16 +70,17 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPanel() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,16 +95,17 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlFormItemPanel(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs index e2cbf974..35238888 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemPrepend.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemPrepend public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPrepend(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -43,16 +45,17 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPrepend() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -67,16 +70,17 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemPrepend() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,16 +95,17 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlFormItemPrepend(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs index 76048c14..d5c5233a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemStaticText.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,15 +19,16 @@ public class UnitTestControlFormItemStaticText public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemStaticText(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,16 +42,17 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemStaticText() { Name = name }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,16 +66,17 @@ public void Name(string name, string expected) public void Label(string label, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemStaticText() { Label = label }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,16 +90,17 @@ public void Label(string label, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlFormItemStaticText() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs index ff781da3..ac18aa73 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlHtml.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlHtml public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlHtml(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Html(string rawHtml, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlHtml() { Html = rawHtml }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs index 08f4f534..33852926 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlIcon.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlIcon public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlIcon(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlIcon() { Title = title }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -61,15 +64,16 @@ public void Title(string title, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlIcon() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -86,15 +90,16 @@ public void Icon(TypeIcon icon, string expected) public void Size(TypeSizeText size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlIcon() { Size = new PropertySizeText(size) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -111,15 +116,16 @@ public void Size(TypeSizeText size, string expected) public void VerticalAlignment(TypeVerticalAlignment verticalAlignment, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlIcon() { VerticalAlignment = verticalAlignment }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs index 3cf7e60c..218ee49a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlImage.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlImage public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlImage(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlImage() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -63,15 +66,16 @@ public void Uri(string uri, string expected) public void Width(int width, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlImage() { Width = width, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -86,15 +90,16 @@ public void Width(int width, string expected) public void Height(int height, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlImage() { Height = height, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -110,15 +115,16 @@ public void Height(int height, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlImage() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs index 92d83aaa..d470746b 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLine.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlLine public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLine(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void Color(TypeColorLine color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLine() { Color = new PropertyColorLine(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs index f6f186e7..7cc39ccf 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -156,15 +163,16 @@ public void Tooltip(string tooltip, string expected) public void Icon() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Icon = new PropertyIcon(TypeIcon.Star) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } @@ -176,8 +184,9 @@ public void Icon() public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -190,12 +199,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs index c4d7a4b7..ed66e3e7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlLinkList.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlLinkList public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Name(string name, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList() { Name = name, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,8 +73,9 @@ public void Name(string name, string expected) public void NameColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList() { Name = "abc", @@ -79,7 +83,7 @@ public void NameColor(TypeColorText color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void NameColor(TypeColorText color, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -123,15 +128,16 @@ public void Icon(TypeIcon icon, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -143,14 +149,15 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLinkList(); // test execution control.Add(new ControlLink() { Text = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs index 81b8e828..5e8d409c 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlList.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlList public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlList(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -46,15 +48,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlList() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -71,15 +74,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Layout(TypeLayoutList layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlList() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -92,12 +96,13 @@ public void Layout(TypeLayoutList layout, string expected) public void Add(IEnumerable items, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlList(null, items.ToArray()); // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs index cf969bfc..b4c07bc3 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemButton.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlListItemButton public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemButton(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemButton(null) { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -59,8 +62,9 @@ public void Active(TypeActive active, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlListItemButton(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlListItemButton(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlListItemButton(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -73,12 +77,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html1); AssertExtensions.EqualWithPlaceholders(@"", html2); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs index da324861..8b2583d1 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlListItemLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlListItemLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -158,15 +165,16 @@ public void Tooltip(string tooltip, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -180,15 +188,16 @@ public void Icon(TypeIcon icon, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlListItemLink(null) { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -200,8 +209,9 @@ public void Active(TypeActive active, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlListItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlListItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlListItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -214,12 +224,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html1); AssertExtensions.EqualWithPlaceholders(@"", html2); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs index 74acba52..654eec52 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModal.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlModal public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlModal(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Header(string header, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlModal() { Header = header }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs index 9d295498..9b397feb 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlModalForm.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlModalForm public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlModalForm(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Header(string header, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlModalForm() { Header = header }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -60,15 +63,16 @@ public void Header(string header, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlModalForm() { }; // test execution control.Add(new ControlFormItemInputTextBox() { Value = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"**", html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs index 95952723..2d0e975b 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlMultipleProgressBar.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlMultipleProgressBar public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlMultipleProgressBar(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Format(TypeFormatProgress format, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlMultipleProgressBar() { Format = format }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,8 +67,9 @@ public void Format(TypeFormatProgress format, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var item = new ControlMultipleProgressBarItem() { Text = text }; var control = new ControlMultipleProgressBar(null, item) { @@ -73,7 +77,7 @@ public void Text(string text, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,8 +97,9 @@ public void Text(string text, string expected) public void Color(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var item = new ControlMultipleProgressBarItem() { Color = new PropertyColorText(color) }; var control = new ControlMultipleProgressBar(null, item) { @@ -102,7 +107,7 @@ public void Color(TypeColorText color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -123,8 +128,9 @@ public void Color(TypeColorText color, string expected) public void TextColor(TypeColorText textColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlMultipleProgressBar() { TextColor = new PropertyColorText(textColor), @@ -132,7 +138,7 @@ public void TextColor(TypeColorText textColor, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -146,16 +152,17 @@ public void TextColor(TypeColorText textColor, string expected) public void Value(uint value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var item = new ControlMultipleProgressBarItem() { Value = value }; var control = new ControlMultipleProgressBar(null, item) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs index adc0aced..1224e7d3 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigation.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlNavigation public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigation(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigation() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -69,15 +72,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Layout(TypeLayoutTab layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigation() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -89,14 +93,15 @@ public void Layout(TypeLayoutTab layout, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigation(); // test execution control.Add(new ControlNavigationItemLink() { Text = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs index d92d1545..47cbb30f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemDropdown.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlNavigationItemDropdown public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorButton backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { BackgroundColor = new PropertyColorButton(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -68,15 +71,16 @@ public void BackgroundColor(TypeColorButton backgroundColor, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -90,8 +94,9 @@ public void Size(TypeSizeButton size, string expected) public void Outline(bool outline, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Outline = outline, @@ -99,7 +104,7 @@ public void Outline(bool outline, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -113,15 +118,16 @@ public void Outline(bool outline, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -135,15 +141,16 @@ public void Block(TypeBlockButton block, string expected) public void Toogle(TypeToggleDropdown toogle, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Toogle = toogle }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -158,15 +165,16 @@ public void Toogle(TypeToggleDropdown toogle, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -181,15 +189,16 @@ public void Text(string text, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Tooltip = tooltip, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -204,15 +213,16 @@ public void Tooltip(string tooltip, string expected) public void Value(string value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Value = value, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -226,15 +236,16 @@ public void Value(string value, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -249,15 +260,16 @@ public void Icon(TypeIcon icon, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -271,15 +283,16 @@ public void Active(TypeActive active, string expected) public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown() { AlignmentMenu = alignmentMenu }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -291,14 +304,15 @@ public void AlignmentMenu(TypeAlignmentDropdownMenu alignmentMenu, string expect public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemDropdown(); // test execution control.Add(new ControlDropdownItemLink() { Text = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs index 00dcd674..6bed6e11 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemHeader.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlNavigationItemHeader public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemHeader(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemHeader() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs index 863c07fd..7975cbf3 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlNavigationItemLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlNavigationItemLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -156,15 +163,16 @@ public void Tooltip(string tooltip, string expected) public void Icon() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { Icon = new PropertyIcon(TypeIcon.Star) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } @@ -178,15 +186,16 @@ public void Icon() public void NoWrap(bool noWrap, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlNavigationItemLink() { NoWrap = noWrap }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -198,16 +207,17 @@ public void NoWrap(bool noWrap, string expected) public void Content() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlNavigationItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlNavigationItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlNavigationItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); // test execution - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs index 68c62325..be03217c 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanel.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanel public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanel(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanel() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanel() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanel() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanel(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs index 1d810832..f5743f66 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCallout.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelCallout public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCallout(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCallout() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCallout() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelCallout(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs index 02e7958a..ebc62114 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCard.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelCard public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Header(string header, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard() { Header = header }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -61,15 +64,16 @@ public void Header(string header, string expected) public void HeaderImage(string headerImage, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard() { HeaderImage = headerImage }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -83,15 +87,16 @@ public void HeaderImage(string headerImage, string expected) public void Headline(string headline, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard() { Headline = headline }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -105,15 +110,16 @@ public void Headline(string headline, string expected) public void Footer(string footer, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard() { Footer = footer }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -127,15 +133,16 @@ public void Footer(string footer, string expected) public void FooterImage(string footerImage, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCard() { FooterImage = footerImage }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs index 27d6e468..bcd56157 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelCenter.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelCenter public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCenter(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCenter() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCenter() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelCenter() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelCenter(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs index bc483ceb..886210f1 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFlexbox.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelFlexbox public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -88,15 +92,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Layout(TypeLayoutFlexbox layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Layout = layout, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -113,15 +118,16 @@ public void Layout(TypeLayoutFlexbox layout, string expected) public void Justify(TypeJustifiedFlexbox justify, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Justify = justify, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -138,15 +144,16 @@ public void Justify(TypeJustifiedFlexbox justify, string expected) public void Align(TypeAlignFlexbox align, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Align = align, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -162,15 +169,16 @@ public void Align(TypeAlignFlexbox align, string expected) public void Wrap(TypeWrap wrap, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFlexbox() { Wrap = wrap, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -185,15 +193,16 @@ public void Wrap(TypeWrap wrap, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelFlexbox(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs index 30c37425..d48e3c6d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelFooter.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelFooter public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFooter(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFooter() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelFooter() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelFooter(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs index 3f0b3d70..d0544d5d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelGrid.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelGrid public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelGrid(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelGrid() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelGrid() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelGrid() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelGrid(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs index 9f9ae334..9fadd120 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelHeader.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelHeader public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelHeader(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelHeader() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelHeader() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Fixed(TypeFixed fixedValue, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelHeader() { Fixed = fixedValue }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -110,15 +115,16 @@ public void Fixed(TypeFixed fixedValue, string expected) public void Sticky(TypeSticky sticky, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelHeader() { Sticky = sticky, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -133,15 +139,16 @@ public void Sticky(TypeSticky sticky, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelHeader(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs index a86daa4a..f5d2a4e2 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMain.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelMain public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMain(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMain() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMain() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelMain(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs index 5550a74a..8352647f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelMedia.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelMedia public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { Title = title }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -138,15 +144,16 @@ public void Title(string title, string expected) public void Image(string image, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { Image = image }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -160,15 +167,16 @@ public void Image(string image, string expected) public void ImageWidth(uint? imageWidth, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { ImageWidth = imageWidth }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -182,15 +190,16 @@ public void ImageWidth(uint? imageWidth, string expected) public void ImageHeight(uint? imageHeight, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelMedia() { ImageHeight = imageHeight }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -205,15 +214,16 @@ public void ImageHeight(uint? imageHeight, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelMedia(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs index a07a8de0..51d93a1a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelNavbar.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelNavbar public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelNavbar(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelNavbar() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelNavbar() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelNavbar() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelNavbar(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs index 89ca29d4..f865acbf 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelSplit.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelSplit public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelSplit(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Orientation(TypeOrientationSplit orientation, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelSplit() { Orientation = orientation, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -68,15 +71,16 @@ public void Orientation(TypeOrientationSplit orientation, string expected) public void SplitterColor(TypeColorBackground splitterColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelSplit() { SplitterColor = new PropertyColorBackground(splitterColor), }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,8 +95,9 @@ public void SplitterColor(TypeColorBackground splitterColor, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance1 = Activator.CreateInstance(child, [null]) as IControl; var childInstance2 = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelSplit(); @@ -101,7 +106,7 @@ public void Add(Type child, string expected) control.AddPanel1(childInstance1); control.AddPanel2(childInstance2); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs index de7be8ab..c3462ff4 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelToast.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelToast public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelToast(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelToast() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -70,15 +73,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelToast() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -93,15 +97,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelToast() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -116,15 +121,16 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelToast(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs index 682ec4d5..8d8705fc 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlPanelTool.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlPanelTool public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelTool(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -42,15 +44,16 @@ public void Id(string id, string expected) public void Direction(TypeDirection direction, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelTool() { Direction = direction, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -65,15 +68,16 @@ public void Direction(TypeDirection direction, string expected) public void Fluid(TypePanelContainer fluid, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlPanelTool() { Fluid = fluid, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,8 +92,9 @@ public void Fluid(TypePanelContainer fluid, string expected) public void Tools(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = new ControlDropdownItemLink() { Text = text }; var control = new ControlPanelTool() { @@ -97,7 +102,7 @@ public void Tools(string text, string expected) // test execution control.Tools.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -112,15 +117,16 @@ public void Tools(string text, string expected) public void Add(Type child, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(child, [null]) as IControl; var control = new ControlPanelTool(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs index bb33f915..6d985617 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlProgressBar.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlProgressBar public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Format(TypeFormatProgress format, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Format = format }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -66,8 +69,9 @@ public void Format(TypeFormatProgress format, string expected) public void Size(TypeSizeProgress size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Size = size, @@ -75,7 +79,7 @@ public void Size(TypeSizeProgress size, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -90,8 +94,9 @@ public void Size(TypeSizeProgress size, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Text = text, @@ -99,7 +104,7 @@ public void Text(string text, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -119,8 +124,9 @@ public void Text(string text, string expected) public void Color(TypeColorProgress color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Color = new PropertyColorProgress(color), @@ -128,7 +134,7 @@ public void Color(TypeColorProgress color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -149,8 +155,9 @@ public void Color(TypeColorProgress color, string expected) public void TextColor(TypeColorText textColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { TextColor = new PropertyColorText(textColor), @@ -158,7 +165,7 @@ public void TextColor(TypeColorText textColor, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -172,16 +179,17 @@ public void TextColor(TypeColorText textColor, string expected) public void Min(uint min, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Min = min }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -195,16 +203,17 @@ public void Min(uint min, string expected) public void Max(uint max, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Max = max }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -218,16 +227,17 @@ public void Max(uint max, string expected) public void Value(uint value, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var form = new ControlForm(); var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlProgressBar() { Value = value }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs index 067d2e3a..d539bf06 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButton.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlSplitButton public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -62,15 +65,16 @@ public void Text(string text, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { BackgroundColor = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -115,8 +120,9 @@ public void BackgroundColor(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { Outline = outline, @@ -124,7 +130,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -138,15 +144,16 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -160,15 +167,16 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButton() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -180,8 +188,9 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlSplitButton(null, new ControlSplitButtonItemLink() { Text = "abc" }); var control2 = new ControlSplitButton(null, [new ControlSplitButtonItemLink() { Text = "abc" }]); var control3 = new ControlSplitButton(null, new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); @@ -194,12 +203,12 @@ public void Add() control5.Add([new ControlSplitButtonItemLink() { Text = "abc" }]); control6.Add(new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); - var html4 = control1.Render(context); - var html5 = control2.Render(context); - var html6 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); var expected = @"
                                                                                                                                                                                                                                                                                            *abc*
                                                                                                                                                                                                                                                                                            "; AssertExtensions.EqualWithPlaceholders(expected, html1); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs index ee8ec22c..32dd3f6d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemDivider.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlSplitButtonItemDivider public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemDivider(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs index cff88d8d..0fbfad7d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemHeader.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlSplitButtonItemHeader public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemHeader(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemHeader() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs index 38e65ddc..3ce36fe7 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonItemLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlSplitButtonItemLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -156,15 +163,16 @@ public void Tooltip(string tooltip, string expected) public void Icon() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonItemLink() { Icon = new PropertyIcon(TypeIcon.Star) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(@"", html.Trim()); } @@ -176,8 +184,9 @@ public void Icon() public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -190,12 +199,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs index 654a611a..350a866c 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlSplitButtonLink.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlSplitButtonLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -39,15 +41,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -62,15 +65,16 @@ public void Text(string text, string expected) public void Size(TypeSizeButton size, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { Size = size }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -88,15 +92,16 @@ public void Size(TypeSizeButton size, string expected) public void BackgroundColor(TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { BackgroundColor = new PropertyColorButton(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -115,8 +120,9 @@ public void BackgroundColor(TypeColorButton color, string expected) public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { Outline = outline, @@ -124,7 +130,7 @@ public void Outline(bool outline, TypeColorButton color, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -138,15 +144,16 @@ public void Outline(bool outline, TypeColorButton color, string expected) public void Block(TypeBlockButton block, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { Block = block }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -160,15 +167,16 @@ public void Block(TypeBlockButton block, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlSplitButtonLink() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -180,8 +188,9 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlSplitButtonLink(null, new ControlSplitButtonItemLink() { Text = "abc" }); var control2 = new ControlSplitButtonLink(null, [new ControlSplitButtonItemLink() { Text = "abc" }]); var control3 = new ControlSplitButtonLink(null, new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); @@ -194,12 +203,12 @@ public void Add() control5.Add([new ControlSplitButtonItemLink() { Text = "abc" }]); control6.Add(new List([new ControlSplitButtonItemLink() { Text = "abc" }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control2.Render(context); - var html4 = control1.Render(context); - var html5 = control2.Render(context); - var html6 = control2.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); var expected = @"
                                                                                                                                                                                                                                                                                            *abc*
                                                                                                                                                                                                                                                                                            "; AssertExtensions.EqualWithPlaceholders(expected, html1); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs index 5c498a99..6a149b5d 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTable.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlTable public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTable(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -46,15 +48,16 @@ public void Id(string id, string expected) public void ColumnLayout(TypesLayoutTableRow layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTable { ColumnLayout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -68,15 +71,16 @@ public void ColumnLayout(TypesLayoutTableRow layout, string expected) public void Responsive(bool responsive, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTable { Responsive = responsive }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -90,15 +94,16 @@ public void Responsive(bool responsive, string expected) public void Striped(bool striped, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTable { Striped = striped }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -112,15 +117,16 @@ public void Striped(bool striped, string expected) public void Reflow(bool reflow, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTable { Reflow = reflow }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs index 480d5149..6633ecb9 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableColumn.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlTableColumn public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableColumn(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableColumn() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -69,15 +72,16 @@ public void Text(string text, string expected) public void Layout(TypesLayoutTableRow layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableColumn() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,15 +95,16 @@ public void Layout(TypesLayoutTableRow layout, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableColumn() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs index 5eb122b3..50b91e10 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTableRow.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlTableRow public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableRow(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -46,15 +48,16 @@ public void Id(string id, string expected) public void Layout(TypesLayoutTableRow layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTableRow() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -69,15 +72,16 @@ public void Layout(TypesLayoutTableRow layout, string expected) public void Add(Type cell, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var childInstance = Activator.CreateInstance(cell, [null]) as IControl; var control = new ControlTableRow(); // test execution control.Add(childInstance); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs index 57f78fc8..a3a3904f 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTag.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlTag public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTag(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -40,15 +42,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTag() { Text = text }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -62,15 +65,16 @@ public void Text(string text, string expected) public void Pill(bool pill, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTag() { Pill = pill }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,15 +95,16 @@ public void Pill(bool pill, string expected) public void Layout(TypeColorBackgroundBadge layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTag() { Layout = new PropertyColorBackgroundBadge(layout) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs index 8cbaf048..80b66597 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlText.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlText public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlText(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,8 +43,9 @@ public void Id(string id, string expected) public void Text(string text, TypeFormatText format, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlText() { Text = text, @@ -50,7 +53,7 @@ public void Text(string text, TypeFormatText format, string expected) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -72,15 +75,16 @@ public void Text(string text, TypeFormatText format, string expected) public void TextColor(TypeColorText color, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlAttribute() { TextColor = new PropertyColorText(color) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs index 5ac6c849..1f11d662 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolBarItemSeperator.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -18,14 +19,15 @@ public class UnitTestControlToolBarItemSeperator public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemDivider(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs index b18edc66..b9bd2c64 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbar.cs @@ -1,6 +1,7 @@ ο»Ώ using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -20,14 +21,15 @@ public class UnitTestControlToolbar public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbar(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -47,15 +49,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbar() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -67,12 +70,13 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbar(null, new ControlToolbarItemButton() { Text = "abc" }); // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"", html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs index 35b3d3db..163f61a3 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlToolbarItemButton.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlToolbarItemButton public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -46,15 +48,16 @@ public void Id(string id, string expected) public void BackgroundColor(TypeColorBackground backgroundColor, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton() { BackgroundColor = new PropertyColorBackground(backgroundColor) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -69,15 +72,16 @@ public void BackgroundColor(TypeColorBackground backgroundColor, string expected public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -92,15 +96,16 @@ public void Text(string text, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton() { Tooltip = tooltip, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -114,15 +119,16 @@ public void Tooltip(string tooltip, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -137,15 +143,16 @@ public void Icon(TypeIcon icon, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlToolbarItemButton() { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -160,15 +167,16 @@ public void Active(TypeActive active, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -183,15 +191,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -208,15 +217,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -228,8 +238,9 @@ public void Target(TypeTarget target, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -242,12 +253,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); Assert.Equal(@"", html1.Trim()); Assert.Equal(@"", html2.Trim()); diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs index 3337e330..cc04db9a 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTree.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlTree : IClassFixture public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTree(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -45,15 +47,16 @@ public void Id(string id, string expected) public void Layout(TypeLayoutTree layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTree() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -67,15 +70,16 @@ public void Layout(TypeLayoutTree layout, string expected) public void Sorted(bool sorted, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTree() { Sorted = sorted }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -88,12 +92,13 @@ public void Sorted(bool sorted, string expected) public void Add(IEnumerable items, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); // test execution var control = new ControlTree(null, items.ToArray()); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs index 9553112b..29d02c53 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItem.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlTreeItem : IClassFixture public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Active(TypeActive active, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem() { Active = active }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); Assert.Equal(expected, html.Trim()); } @@ -68,15 +71,16 @@ public void Active(TypeActive active, string expected) public void Layout(TypeLayoutTreeItem layout, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem() { Layout = layout }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -91,15 +95,16 @@ public void Layout(TypeLayoutTreeItem layout, string expected) public void Expand(TypeExpandTree expand, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem() { Expand = expand }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -111,8 +116,9 @@ public void Expand(TypeExpandTree expand, string expected) public void AddContent() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem() { }; @@ -120,7 +126,7 @@ public void AddContent() // test execution control.Add(new ControlText() { Text = "abc" }); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                          1. abc
                                                                                                                                                                                                                                                                                          2. ", html); } @@ -132,8 +138,9 @@ public void AddContent() public void AddChild() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItem() { }; @@ -141,7 +148,7 @@ public void AddChild() // test execution control.Add(new ControlTreeItem()); - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                          3. ", html); } diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs index 2f23c73b..5b380f18 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlTreeItemLink.cs @@ -1,6 +1,7 @@ ο»Ώusing WebExpress.WebCore.WebHtml; using WebExpress.WebUI.Test.Fixture; using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebControl { @@ -19,14 +20,15 @@ public class UnitTestControlTreeItemLink public void Id(string id, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink(id) { }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -41,15 +43,16 @@ public void Id(string id, string expected) public void Text(string text, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Text = text, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -64,15 +67,16 @@ public void Text(string text, string expected) public void Uri(string uri, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Uri = uri, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -87,15 +91,16 @@ public void Uri(string uri, string expected) public void Title(string title, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Title = title, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -112,15 +117,16 @@ public void Title(string title, string expected) public void Target(TypeTarget target, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Target = target, }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -136,15 +142,16 @@ public void Target(TypeTarget target, string expected) public void Tooltip(string tooltip, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Tooltip = tooltip }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -158,15 +165,16 @@ public void Tooltip(string tooltip, string expected) public void Icon(TypeIcon icon, string expected) { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control = new ControlTreeItemLink() { Icon = new PropertyIcon(icon) }; // test execution - var html = control.Render(context); + var html = control.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(expected, html); } @@ -178,8 +186,9 @@ public void Icon(TypeIcon icon, string expected) public void Add() { // preconditions - UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var context = UnitTestControlFixture.CrerateRenderContextMock(); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); var control1 = new ControlTreeItemLink(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); var control2 = new ControlTreeItemLink(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); var control3 = new ControlTreeItemLink(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); @@ -192,12 +201,12 @@ public void Add() control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); - var html1 = control1.Render(context); - var html2 = control2.Render(context); - var html3 = control3.Render(context); - var html4 = control4.Render(context); - var html5 = control5.Render(context); - var html6 = control6.Render(context); + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                          4. ", html1); AssertExtensions.EqualWithPlaceholders(@"
                                                                                                                                                                                                                                                                                          5. ", html2); diff --git a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs index ff97f986..e886c3fe 100644 --- a/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs +++ b/src/WebExpress.WebUI.Test/WebFragment/UnitTestFragmentManager.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.WebScope; using WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.Test.WebFragment { @@ -50,6 +51,7 @@ public void Id(Type applicationType, Type fragmentType, string id) [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlPanelTool), typeof(IScope), @"
                                                                                                                                                                                                                                                                                            *
                                                                                                                                                                                                                                                                                            TestFragmentControlPanelTool
                                                                                                                                                                                                                                                                                            ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlSplitButtonItemLink), typeof(IScope), @"TestFragmentControlSplitButtonItemLink")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlTree), typeof(IScope), @"
                                                                                                                                                                                                                                                                                            ")] + [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlForm), typeof(IScope), @"
                                                                                                                                                                                                                                                                                            *
                                                                                                                                                                                                                                                                                            ")] [InlineData(typeof(TestApplication), typeof(TestSectionFragmentControlModalForm), typeof(IScope), @"
                                                                                                                                                                                                                                                                                            *Close
                                                                                                                                                                                                                                                                                            *")] public void Render(Type applicationType, Type sectionType, Type scopeType, string expected) { @@ -57,9 +59,10 @@ public void Render(Type applicationType, Type sectionType, Type scopeType, strin var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault(); var renderContext = UnitTestControlFixture.CrerateRenderContextMock(application, [scopeType]); + var visualTree = new VisualTreeControl(componentHub, renderContext.PageContext); // test execution - var html = componentHub.FragmentManager.Render(renderContext, sectionType); + var html = componentHub.FragmentManager.Render(renderContext, visualTree, sectionType); Assert.NotNull(html); Assert.NotEmpty(html); diff --git a/src/WebExpress.WebUI/WebControl/Control.cs b/src/WebExpress.WebUI/WebControl/Control.cs index f918d1af..a570f4e5 100644 --- a/src/WebExpress.WebUI/WebControl/Control.cs +++ b/src/WebExpress.WebUI/WebControl/Control.cs @@ -300,7 +300,8 @@ protected string GetStyles() /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public abstract IHtmlNode Render(IRenderControlContext renderContext); + public abstract IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree); } } diff --git a/src/WebExpress.WebUI/WebControl/ControlArlert.cs b/src/WebExpress.WebUI/WebControl/ControlArlert.cs index a233ad7f..fd36bd41 100644 --- a/src/WebExpress.WebUI/WebControl/ControlArlert.cs +++ b/src/WebExpress.WebUI/WebControl/ControlArlert.cs @@ -58,8 +58,9 @@ public ControlAlert(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var head = new HtmlElementTextSemanticsStrong ( diff --git a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs index 27670a4f..db7cc71b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAttribute.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAttribute.cs @@ -49,8 +49,9 @@ public ControlAttribute(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (!Enable) { diff --git a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs index f9cb8402..fa7715f3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlAvatar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlAvatar.cs @@ -47,8 +47,9 @@ public ControlAvatar(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var img = default(HtmlElement); @@ -81,7 +82,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Id); - return new HtmlList(html, Modal.Render(renderContext)); + return new HtmlList(html, Modal.Render(renderContext, visualTree)); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlBadge.cs b/src/WebExpress.WebUI/WebControl/ControlBadge.cs index 960f49a4..2d32d944 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBadge.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBadge.cs @@ -68,8 +68,9 @@ public ControlBadge(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (Uri != null) { diff --git a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs index 782be6c6..81d829c7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs +++ b/src/WebExpress.WebUI/WebControl/ControlBreadcrumb.cs @@ -1,5 +1,7 @@ -ο»Ώusing WebExpress.WebCore.Internationalization; +ο»Ώusing System; +using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebUri; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl @@ -13,7 +15,7 @@ public class ControlBreadcrumb : Control /// /// Return or sets the uri. /// - public string Uri { get; set; } + public UriResource Uri { get; set; } /// /// Returns or sets the name to display when the breadcrumb is empty. @@ -54,8 +56,9 @@ public ControlBreadcrumb(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentOl() { @@ -66,7 +69,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (!string.IsNullOrWhiteSpace(Prefix)) { - html.Elements.Add + html.Add ( new HtmlElementTextContentLi ( @@ -81,24 +84,31 @@ public override IHtmlNode Render(IRenderControlContext renderContext) ); } - foreach (var part in renderContext.Request?.Uri.PathSegments) + if (Uri == null) { - if (part.Display != null) + return html; + } + + var takeLast = Math.Min(TakeLast, Uri.PathSegments.Count); + var from = Uri.PathSegments.Count - takeLast; + + for (int i = from + 1; i < Uri.PathSegments.Count + 1; i++) + { + var path = Uri.Take(i); + + if (path.Display != null) { - var display = part.GetDisplay(renderContext.Request?.Culture); - var href = part.ToString(); + var display = I18N.Translate(renderContext.Request?.Culture, path.Display); + var href = path.ToString(); - html.Elements.Add + html.Add ( new HtmlElementTextContentLi ( - //new ControlIcon(Page) - //{ - // Icon = path.Icon - //}.ToHtml(), new HtmlElementTextSemanticsA(display) { - Href = href + Href = href, + Class = "link" } ) { @@ -108,40 +118,6 @@ public override IHtmlNode Render(IRenderControlContext renderContext) } } - //var takeLast = Math.Min(TakeLast, resourceUri.Path.Count); - //var from = resourceUri.Path.Count - takeLast; - - //for (int i = from + 1; i < resourceUri.Path.Count + 1; i++) - //{ - // var path = resourceUri.Take(i); - - // if (path.Display != null) - // { - // var display = I18N(context.Culture, path.Display); - // var href = path.ToString(); - - // html.Elements.Add - // ( - // new HtmlElementTextContentLi - // ( - // //new ControlIcon(Page) - // //{ - // // Icon = path.Icon - // //}.ToHtml(), - // new HtmlElementTextSemanticsA(display) - // { - // Href = href, - // Class = "link" - // } - // ) - // { - // Class = "breadcrumb-item" - // } - // ); - // } - //} - //} - return html; } } diff --git a/src/WebExpress.WebUI/WebControl/ControlButton.cs b/src/WebExpress.WebUI/WebControl/ControlButton.cs index 22f79aca..07b14813 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButton.cs @@ -142,8 +142,9 @@ public void Add(IEnumerable items) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementFieldButton() { @@ -169,7 +170,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -184,7 +185,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (_content.Count != 0) { - html.Add(_content.Select(x => x.Render(renderContext)).ToArray()); + html.Add(_content.Select(x => x.Render(renderContext, visualTree)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) @@ -204,7 +205,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(renderContext)); + return new HtmlList(html, Modal.Modal.Render(renderContext, visualTree)); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs index aac4c497..47e8d442 100644 --- a/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlButtonLink.cs @@ -35,8 +35,9 @@ public ControlButtonLink(string id = null, params IControl[] content) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var text = I18N.Translate(Text); @@ -64,7 +65,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(text)) @@ -74,7 +75,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (Content.Any()) { - html.Add(Content.Select(x => x.Render(renderContext)).ToArray()); + html.Add(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()); } if (Modal == null || Modal.Type == TypeModal.None) @@ -96,7 +97,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(renderContext)); + return new HtmlList(html, Modal.Modal.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Tooltip)) diff --git a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs index 3436d23a..f5b8be67 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCanvas.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCanvas.cs @@ -25,8 +25,9 @@ public ControlCanvas(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementScriptingCanvas() { diff --git a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs index 4bd96628..9ca96453 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCardCounter.cs @@ -42,8 +42,9 @@ public ControlCardCounter(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextSemanticsSpan() { @@ -60,7 +61,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Icon = Icon, TextColor = TextColor, HorizontalAlignment = TypeHorizontalAlignment.Right - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } var text = new ControlText(string.IsNullOrWhiteSpace(Id) ? null : Id + "_header") @@ -76,7 +77,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) TextColor = new PropertyColorText(TypeColorText.Muted) }; - html.Add(new ControlPanel(null, text, info) { }.Render(renderContext)); + html.Add(new ControlPanel(null, text, info) { }.Render(renderContext, visualTree)); if (Progress.HasValue) { @@ -87,7 +88,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) BackgroundColor = BackgroundColor, //Color = Color, Size = TypeSizeProgress.Small - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs index fe1c2704..615fbc62 100644 --- a/src/WebExpress.WebUI/WebControl/ControlCarousel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlCarousel.cs @@ -59,8 +59,9 @@ public void Clear() /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { // indicators var indicators = new HtmlElementTextContentUl() { Class = "carousel-indicators" }; @@ -83,7 +84,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) var inner = new HtmlElementTextContentDiv() { Class = "carousel-inner" }; foreach (var v in Items) { - var i = new HtmlElementTextContentDiv(v?.Control.Render(renderContext)) + var i = new HtmlElementTextContentDiv(v?.Control.Render(renderContext, visualTree)) { Class = index == 0 ? "carousel-item active" : "carousel-item" }; diff --git a/src/WebExpress.WebUI/WebControl/ControlChart.cs b/src/WebExpress.WebUI/WebControl/ControlChart.cs index 219796c3..dae9d90f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlChart.cs +++ b/src/WebExpress.WebUI/WebControl/ControlChart.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebUri; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl @@ -78,10 +79,11 @@ public ControlChart(string id = null, params ControlChartDataset[] datasets) /// Initializes the control. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. - public void Initialize(IRenderControlContext renderContext) + /// The visual tree representing the control's structure. + protected void Initialize(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - //renderContext.AddHeaderScriptLinks(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/js/Chart.min.js")); - //renderContext.AddCssLinks(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/css/Chart.min.css")); + visualTree.AddHeaderScriptLink(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/js/Chart.min.js")); + visualTree.AddCssLink(UriResource.Combine(renderContext.PageContext?.ApplicationContext?.ContextPath, "/assets/css/Chart.min.css")); var builder = new StringBuilder(); var data = new List(); @@ -132,17 +134,18 @@ public void Initialize(IRenderControlContext renderContext) builder.AppendLine($"var chart_{Id} = new Chart(document.getElementById('{Id}').getContext('2d'), config_{Id});"); - renderContext.AddScript($"chart_{Id}", builder.ToString()); + visualTree.AddScript($"chart_{Id}", builder.ToString()); } /// /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - Initialize(renderContext); + Initialize(renderContext, visualTree); var html = new HtmlElementScriptingCanvas() { diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs index 8ee985a0..59b71fed 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdown.cs @@ -168,8 +168,9 @@ public void AddHeader(string text) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { @@ -203,7 +204,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -248,8 +249,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) x == null || x is ControlDropdownItemDivider || x is ControlLine ? new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } + x.Render(renderContext, visualTree) : + new HtmlElementTextContentLi(x.Render(renderContext, visualTree)) { Class = "dropdown-item " + ((x as ControlDropdownItemLink).Active == TypeActive.Disabled ? "disabled" : "") } ).ToArray() ) { @@ -265,7 +266,7 @@ x is ControlDropdownItemHeader ? .Select(x => x as ControlDropdownItemLink) .Select(x => x.Modal) .Where(x => x.Type == TypeModal.Modal) - .Select(x => x.Modal.Render(renderContext)); + .Select(x => x.Modal.Render(renderContext, visualTree)); return new HtmlList(html, modals); } diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs index 52afab0c..8fab2bf9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemDivider.cs @@ -24,8 +24,9 @@ public ControlDropdownItemDivider(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs index 401ba198..a99fb21e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemHeader.cs @@ -27,8 +27,9 @@ public ControlDropdownItemHeader(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext.Request.Culture, Text))) { diff --git a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs index 2c25e717..cbb18bdd 100644 --- a/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlDropdownItemLink.cs @@ -24,12 +24,13 @@ public ControlDropdownItemLink(string id = null, params IControl[] content) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var param = ""; // GetParams(context?.Page); - var html = new HtmlElementTextSemanticsA(Controls.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(Controls.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), @@ -53,7 +54,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None, PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None) - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) diff --git a/src/WebExpress.WebUI/WebControl/ControlForm.cs b/src/WebExpress.WebUI/WebControl/ControlForm.cs index 029b8c85..34362d97 100644 --- a/src/WebExpress.WebUI/WebControl/ControlForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlForm.cs @@ -297,19 +297,21 @@ public virtual void Process(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return Render(renderContext, Items); + return Render(renderContext, visualTree, Items); } /// /// Convert to html. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// The form items. /// The control as html. - public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + public virtual IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree, IEnumerable items) { var renderFormContext = new RenderControlFormContext(renderContext, this); var fill = false; @@ -382,8 +384,8 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable Enctype = TypeEnctype.None }; - form.Add(FormId.Render(renderFormContext)); - form.Add(SubmitType.Render(renderFormContext)); + form.Add(FormId.Render(renderFormContext, visualTree)); + form.Add(SubmitType.Render(renderFormContext, visualTree)); var header = new HtmlElementSectionHeader(); header.Add(new ControlProgressBar() @@ -393,7 +395,7 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three), Styles = { "height: 3px;", "display: none;" }, Value = 0 - }.Render(renderFormContext)); + }.Render(renderFormContext, visualTree)); //header.Elements.AddRange(HeaderPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); //header.Elements.AddRange(HeaderPrimary.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); @@ -419,12 +421,12 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable Text = I18N.Translate(renderContext.Request?.Culture, v.Text), Dismissible = TypeDismissibleAlert.Dismissible, Fade = TypeFade.FadeShow - }.Render(renderFormContext)); + }.Render(renderFormContext, visualTree)); } foreach (var item in items.Where(x => x is ControlFormItemInputHidden)) { - form.Add(item.Render(renderFormContext)); + form.Add(item.Render(renderFormContext, visualTree)); } var main = new HtmlElementSectionMain(); @@ -443,10 +445,10 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable group.Items.Add(item); } - main.Add(group.Render(renderFormContext)); + main.Add(group.Render(renderFormContext, visualTree)); var buttonPannel = new HtmlElementTextContentDiv(); - buttonPannel.Add(Buttons.Select(x => x.Render(renderFormContext))); + buttonPannel.Add(Buttons.Select(x => x.Render(renderFormContext, visualTree))); var footer = new HtmlElementSectionFooter(); //footer.Elements.AddRange(FooterPreferences.SelectMany(x => x.CreateInstance(context.Page, context.Request)).Select(x => x.Render(context))); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs index 3d9e0620..216eb7d2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItem.cs @@ -36,19 +36,21 @@ public ControlFormItem(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public abstract IHtmlNode Render(IRenderControlFormContext renderContext); + public abstract IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree); /// /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (renderContext is IRenderControlFormContext formContext) { - return Render(formContext); + return Render(formContext, visualTree); } return null; diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs index 1142313e..99d63d3e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemButton.cs @@ -3,6 +3,7 @@ using System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -172,8 +173,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert to html. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// The control as html. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementFieldButton() { @@ -201,7 +203,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -211,7 +213,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) if (_content.Count > 0) { - html.Add(Content.Select(x => x.Render(renderContext))); + html.Add(Content.Select(x => x.Render(renderContext, visualTree))); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs index 60fd419b..592a792f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumn.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Collections.Generic; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -53,8 +54,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -90,24 +92,24 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) { icon.Classes.Add("me-2 pt-1"); - row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderContext)) { }); + row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext, visualTree), label.Render(renderContext, visualTree)) { }); } else { - row.Add(new HtmlElementTextContentDiv(label.Render(renderContext))); + row.Add(new HtmlElementTextContentDiv(label.Render(renderContext, visualTree))); } - row.Add(new HtmlElementTextContentDiv(item.Render(renderContext)) { }); + row.Add(new HtmlElementTextContentDiv(item.Render(renderContext, visualTree)) { }); if (input != null) { - row.Add(new HtmlElementTextContentDiv(help.Render(renderContext))); + row.Add(new HtmlElementTextContentDiv(help.Render(renderContext, visualTree))); } } else { row.Add(new HtmlElementTextContentDiv()); - row.Add(item.Render(renderGroupContext)); + row.Add(item.Render(renderGroupContext, visualTree)); row.Add(new HtmlElementTextContentDiv()); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs index 75a0eecb..b0a968f9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnHorizontal.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -46,8 +47,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -100,28 +102,28 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) if (icon.Icon != null) { icon.Classes.Add("me-2 pt-1"); - row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext), label.Render(renderGroupContext)) + row.Add(new HtmlElementTextContentDiv(icon.Render(renderContext, visualTree), label.Render(renderGroupContext, visualTree)) { Style = "display: flex;" }); } else { - row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext, visualTree))); } - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree))); if (!string.IsNullOrWhiteSpace(input?.Help)) { - row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext, visualTree))); } div.Add(table); } else { - div.Add(item.Render(renderGroupContext)); + div.Add(item.Render(renderGroupContext, visualTree)); } html.Add(div); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs index 7ecb07c7..d03c01f9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnMix.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -37,8 +38,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -91,30 +93,30 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) if (icon.Icon != null) { icon.Classes.Add("me-2 pt-1"); - row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext, visualTree), label.Render(renderGroupContext, visualTree)) { Style = "display: flex;" }); } else { - row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext, visualTree))); } if (!string.IsNullOrWhiteSpace(input?.Help)) { - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext), help.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree), help.Render(renderGroupContext, visualTree))); } else { - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree))); } div.Add(table); } else { - div.Add(item.Render(renderGroupContext)); + div.Add(item.Render(renderGroupContext, visualTree)); } html.Add(div); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs index d08fa050..cd16775d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupColumnVertical.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -37,8 +38,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -88,28 +90,28 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) if (icon.Icon != null) { icon.Classes.Add("me-2 pt-1"); - fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext, visualTree), label.Render(renderGroupContext, visualTree)) { Style = "display: flex;" }); } else { - fieldset.Add(label.Render(renderGroupContext)); + fieldset.Add(label.Render(renderGroupContext, visualTree)); } - fieldset.Add(item.Render(renderGroupContext)); + fieldset.Add(item.Render(renderGroupContext, visualTree)); if (!string.IsNullOrWhiteSpace(input?.Help)) { - fieldset.Add(help.Render(renderGroupContext)); + fieldset.Add(help.Render(renderGroupContext, visualTree)); } div.Add(fieldset); } else { - div.Add(item.Render(renderGroupContext)); + div.Add(item.Render(renderGroupContext, visualTree)); } html.Add(div); diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs index 9e991ded..78897428 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupHorizontal.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -36,8 +37,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -73,24 +75,24 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) { icon.Classes.Add("me-2 pt-1"); - row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext)) { }); + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext, visualTree), label.Render(renderGroupContext, visualTree)) { }); } else { - row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext)) { }); + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext, visualTree)) { }); } - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext)) { }); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree)) { }); if (!string.IsNullOrWhiteSpace(input?.Help)) { - row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(help.Render(renderGroupContext, visualTree))); } } else { row.Add(new HtmlElementTextContentDiv()); - row.Add(item.Render(renderGroupContext)); + row.Add(item.Render(renderGroupContext, visualTree)); row.Add(new HtmlElementTextContentDiv()); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs index 60083268..180ac9d7 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupMix.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -36,8 +37,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -72,26 +74,26 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) { icon.Classes.Add("me-2 pt-1"); - row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext), label.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(icon.Render(renderGroupContext, visualTree), label.Render(renderGroupContext, visualTree))); } else { - row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(label.Render(renderGroupContext, visualTree))); } if (!string.IsNullOrWhiteSpace(input?.Help)) { - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext), help.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree), help.Render(renderGroupContext, visualTree))); } else { - row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext))); + row.Add(new HtmlElementTextContentDiv(item.Render(renderGroupContext, visualTree))); } } else { row.Add(new HtmlElementTextContentDiv()); - row.Add(item.Render(renderGroupContext)); + row.Add(item.Render(renderGroupContext, visualTree)); row.Add(new HtmlElementTextContentDiv()); } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs index 0831f399..fc381600 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemGroupVertical.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -36,8 +37,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var renderGroupContext = new RenderControlFormGroupContext(renderContext, this); @@ -67,28 +69,28 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) if (icon.Icon != null) { icon.Classes.Add("me-2 pt-1"); - fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext), label.Render(renderGroupContext)) + fieldset.Add(new HtmlElementTextSemanticsSpan(icon.Render(renderGroupContext, visualTree), label.Render(renderGroupContext, visualTree)) { Style = "display: flex;" }); } else { - fieldset.Add(label.Render(renderGroupContext)); + fieldset.Add(label.Render(renderGroupContext, visualTree)); } - fieldset.Add(item.Render(renderGroupContext)); + fieldset.Add(item.Render(renderGroupContext, visualTree)); if (!string.IsNullOrWhiteSpace(input?.Help)) { - fieldset.Add(help.Render(renderGroupContext)); + fieldset.Add(help.Render(renderGroupContext, visualTree)); } html.Add(fieldset); } else { - html.Add(item?.Render(renderGroupContext)); + html.Add(item?.Render(renderGroupContext, visualTree)); } } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs index 4f2a99fa..e3800421 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemHelpText.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -44,8 +45,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementTextSemanticsSmall() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs index 4c9190ab..dbcde5e2 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCheckbox.cs @@ -1,6 +1,7 @@ ο»Ώusing System; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -49,8 +50,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv ( diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs index 7f7defca..fd565770 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputCombobox.cs @@ -2,6 +2,7 @@ using System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -59,8 +60,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementFieldSelect() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs index 3d5ab3a7..125d2394 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputDatepicker.cs @@ -1,4 +1,5 @@ ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -74,8 +75,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { //if (Disabled) //{ diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs index 5106cf19..00ccb7b4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputFile.cs @@ -1,5 +1,6 @@ ο»Ώusing System.Collections.Generic; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -76,8 +77,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { switch (ValidationResult) { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs index 40499275..8968be6a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputGroup.cs @@ -1,5 +1,6 @@ ο»Ώusing System.Collections.Generic; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -52,10 +53,11 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { - return Group?.Render(renderContext); + return Group?.Render(renderContext, visualTree); } /// diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs index 5226f00c..946415b4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputHidden.cs @@ -1,4 +1,5 @@ ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -30,8 +31,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementFieldInput() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs index 1c31755b..cd60b9cc 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputMove.cs @@ -4,6 +4,7 @@ using System.Text.Json; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -74,8 +75,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var classes = Classes.ToList(); @@ -100,7 +102,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) Style = GetStyles() }; - renderContext.AddScript(Id, GetScript($"selection-move-{Id}", string.Join(" ", classes))); + visualTree.AddScript(Id, GetScript($"selection-move-{Id}", string.Join(" ", classes))); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs index 49ff3120..244824a1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputRadio.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -59,8 +60,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { if (!string.IsNullOrWhiteSpace(Value)) { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs index afa89344..f2b7b2f8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputSelection.cs @@ -3,6 +3,7 @@ using System.Text; using System.Text.Json; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -91,8 +92,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var classes = Classes.ToList(); @@ -117,7 +119,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) Style = GetStyles() }; - renderContext.AddScript(Id, GetScript(Id, string.Join(" ", classes))); + visualTree.AddScript(Id, GetScript(Id, string.Join(" ", classes))); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs index e7d055d2..76e8f0cb 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemInputTextBox.cs @@ -2,6 +2,7 @@ using System.Linq; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -91,8 +92,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var id = Id ?? Guid.NewGuid().ToString(); @@ -117,7 +119,7 @@ public override IHtmlNode Render(IRenderControlFormContext renderContext) { var initializeCode = $"$(document).ready(function() {{ $('#{id}').summernote({{ tabsize: 2, height: '{Rows}rem', lang: 'de-DE' }}); }});"; - renderContext.AddScript(id, initializeCode); + visualTree.AddScript(id, initializeCode); AutoInitialize = false; } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs index 47a7f11b..e932fe95 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemLabel.cs @@ -1,5 +1,6 @@ ο»Ώusing WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -39,8 +40,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementFieldLabel() { diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs index 3b6eb246..bef48d18 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPanel.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -127,10 +128,11 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs index fd53256a..df07bd54 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemPrepend.cs @@ -1,4 +1,5 @@ ο»Ώusing WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -21,11 +22,12 @@ public ControlFormItemPrepend(string id = null, params Control[] content) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { Classes.Add("input-group-prepend"); - var html = base.Render(renderContext); + var html = base.Render(renderContext, visualTree); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs index 61fe3847..221bc9a0 100644 --- a/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlFormItemStaticText.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Collections.Generic; using WebExpress.WebCore.Internationalization; using WebExpress.WebCore.WebHtml; +using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl { @@ -40,8 +41,9 @@ public override void Initialize(IRenderControlFormContext renderContext) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlFormContext renderContext) + public override IHtmlNode Render(IRenderControlFormContext renderContext, IVisualTreeControl visualTree) { var c = new List { diff --git a/src/WebExpress.WebUI/WebControl/ControlHtml.cs b/src/WebExpress.WebUI/WebControl/ControlHtml.cs index f8480ea9..e67a639e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlHtml.cs +++ b/src/WebExpress.WebUI/WebControl/ControlHtml.cs @@ -27,8 +27,9 @@ public ControlHtml(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlRaw { diff --git a/src/WebExpress.WebUI/WebControl/ControlIcon.cs b/src/WebExpress.WebUI/WebControl/ControlIcon.cs index a1381856..ca875621 100644 --- a/src/WebExpress.WebUI/WebControl/ControlIcon.cs +++ b/src/WebExpress.WebUI/WebControl/ControlIcon.cs @@ -54,8 +54,9 @@ public ControlIcon(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (Icon.IsUserIcon) { diff --git a/src/WebExpress.WebUI/WebControl/ControlImage.cs b/src/WebExpress.WebUI/WebControl/ControlImage.cs index f1eac7c6..efdc4ac8 100644 --- a/src/WebExpress.WebUI/WebControl/ControlImage.cs +++ b/src/WebExpress.WebUI/WebControl/ControlImage.cs @@ -42,8 +42,9 @@ public ControlImage(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { Classes.Add(HorizontalAlignment.ToClass()); diff --git a/src/WebExpress.WebUI/WebControl/ControlLine.cs b/src/WebExpress.WebUI/WebControl/ControlLine.cs index b0f2cc98..f00ce7cd 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLine.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLine.cs @@ -35,8 +35,9 @@ public ControlLine(string id = null) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentHr() { diff --git a/src/WebExpress.WebUI/WebControl/ControlLink.cs b/src/WebExpress.WebUI/WebControl/ControlLink.cs index 487b5133..40395662 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLink.cs @@ -188,12 +188,13 @@ private string GetParams(Request request) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var param = GetParams(renderContext?.Request); - var html = new HtmlElementTextSemanticsA(_controls.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(_controls.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = Css.Concatenate("link", GetClasses()), @@ -217,7 +218,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None, PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None) - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -244,7 +245,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.AddUserAttribute("data-bs-toggle", "modal"); html.AddUserAttribute("data-bs-target", "#" + Modal.Modal.Id); - return new HtmlList(html, Modal.Modal.Render(renderContext)); + return new HtmlList(html, Modal.Modal.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Tooltip)) diff --git a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs index 157a43ce..9af9cdbe 100644 --- a/src/WebExpress.WebUI/WebControl/ControlLinkList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlLinkList.cs @@ -105,8 +105,9 @@ public virtual void Remove(IControlLink link) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var icon = new HtmlElementTextSemanticsSpan() { @@ -131,7 +132,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Add(Links?.Select(x => x.Render(renderContext))); + html.Add(Links?.Select(x => x.Render(renderContext, visualTree))); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlList.cs b/src/WebExpress.WebUI/WebControl/ControlList.cs index 8bb2d1b1..5dfc4425 100644 --- a/src/WebExpress.WebUI/WebControl/ControlList.cs +++ b/src/WebExpress.WebUI/WebControl/ControlList.cs @@ -106,21 +106,23 @@ public void Remove(ControlListItem item) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. - /// - public override IHtmlNode Render(IRenderControlContext renderContext) + /// The visual tree representing the control's structure. + /// An HTML node representing the rendered control. + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return Render(renderContext, Items); + return Render(renderContext, visualTree, Items); } /// /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// The list entries. /// An HTML node representing the rendered control. - public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + public virtual IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree, IEnumerable items) { - var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToList(); + var li = items.Where(x => x.Enable).Select(x => x.Render(renderContext, visualTree)).ToList(); switch (Layout) { case TypeLayoutList.Horizontal: diff --git a/src/WebExpress.WebUI/WebControl/ControlListItem.cs b/src/WebExpress.WebUI/WebControl/ControlListItem.cs index 9598bd5d..ebf51280 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItem.cs @@ -97,10 +97,11 @@ public virtual void Remove(IControl control) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementTextContentLi(Content.Where(x => x.Enable).Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementTextContentLi(Content.Where(x => x.Enable).Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs index be509297..8874f58e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemButton.cs @@ -27,10 +27,11 @@ public ControlListItemButton(string id = null, params IControl[] content) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementFieldButton(Content.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementFieldButton(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = Css.Concatenate("list-group-item-action", GetClasses()), diff --git a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs index 866dc7e5..665be4da 100644 --- a/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlListItemLink.cs @@ -91,12 +91,13 @@ public string GetParams() /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var param = GetParams(); - var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = Css.Concatenate("list-group-item-action", GetClasses()), @@ -121,7 +122,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) diff --git a/src/WebExpress.WebUI/WebControl/ControlModal.cs b/src/WebExpress.WebUI/WebControl/ControlModal.cs index 9e90ceab..c08025d6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModal.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModal.cs @@ -116,8 +116,9 @@ public virtual void Remove(IControl control) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var classes = Classes.ToList(); classes.Add("modal"); @@ -144,7 +145,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Class = "modal-header" }; - var body = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) + var body = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Class = "modal-body" }; @@ -185,19 +186,19 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (!string.IsNullOrWhiteSpace(OnShownCode)) { var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; - renderContext.AddScript(Id + "_shown", shown); + visualTree.AddScript(Id + "_shown", shown); } if (!string.IsNullOrWhiteSpace(OnHiddenCode)) { var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; - renderContext.AddScript(Id + "_hidden", hidden); + visualTree.AddScript(Id + "_hidden", hidden); } if (ShowIfCreated) { var show = "$('#" + Id + "').modal('show');"; - renderContext.AddScript(Id + "_showifcreated", show); + visualTree.AddScript(Id + "_showifcreated", show); } return html; diff --git a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs index f9d8c866..00233665 100644 --- a/src/WebExpress.WebUI/WebControl/ControlModalForm.cs +++ b/src/WebExpress.WebUI/WebControl/ControlModalForm.cs @@ -114,24 +114,26 @@ private void OnValidatedForm(object sender, ValidationResultEventArgs e) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return Render(renderContext, Form.Items); + return Render(renderContext, visualTree, Form.Items); } /// /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// The form items. /// An HTML node representing the rendered control. - public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable items) + public virtual IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree, IEnumerable items) { var fade = Fade; var classes = Classes.ToList(); - var form = Form.Render(renderContext, items) as HtmlElementFormForm; + var form = Form.Render(renderContext, visualTree, items) as HtmlElementFormForm; classes.Add("modal"); @@ -171,11 +173,11 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable var cancelFooterButton = new ControlButtonLink() { Text = I18N.Translate(renderContext.Request?.Culture, "webexpress.webui:modal.close.label") - }.Render(renderContext) as HtmlElement; + }.Render(renderContext, visualTree) as HtmlElement; cancelFooterButton.AddUserAttribute("data-bs-dismiss", "modal"); - footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderControlFormContext(renderContext, Form)), cancelFooterButton) + footer = new HtmlElementTextContentDiv(submitFooterButton.Render(new RenderControlFormContext(renderContext, Form), visualTree), cancelFooterButton) { Class = "modal-footer d-flex justify-content-between" }; @@ -202,19 +204,19 @@ public virtual IHtmlNode Render(IRenderControlContext renderContext, IEnumerable if (!string.IsNullOrWhiteSpace(OnShownCode)) { var shown = "$('#" + Id + "').on('shown.bs.modal', function(e) { " + OnShownCode + " });"; - renderContext.AddScript(Id + "_shown", shown); + visualTree.AddScript(Id + "_shown", shown); } if (!string.IsNullOrWhiteSpace(OnHiddenCode)) { var hidden = "$('#" + Id + "').on('hidden.bs.modal', function() { " + OnHiddenCode + " });"; - renderContext.AddScript(Id + "_hidden", hidden); + visualTree.AddScript(Id + "_hidden", hidden); } if (ShowIfCreated) { var show = "$('#" + Id + "').modal('show');"; - renderContext.AddScript(Id + "_showifcreated", show); + visualTree.AddScript(Id + "_showifcreated", show); } form.Clear(); diff --git a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs index 00ba0201..2cb8b176 100644 --- a/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlMultipleProgressBar.cs @@ -37,8 +37,9 @@ public ControlMultipleProgressBar(string id = null, params ControlMultipleProgre /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var barClass = new List(); diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs index 582684a3..ab6c6fe1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigation.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigation.cs @@ -141,13 +141,14 @@ public virtual void Remove(IControlNavigationItem item) /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var items = new List(); foreach (var item in Items) { - var i = item.Render(renderContext) as HtmlElement; + var i = item.Render(renderContext, visualTree) as HtmlElement; if (item is ControlNavigationItemLink link) { diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs index c204d59b..a43c1032 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemDropdown.cs @@ -22,10 +22,11 @@ public ControlNavigationItemDropdown(string id = null, params IControlDropdownIt /// Convert the control to HTML. ///
                                                                                                                                                                                                                                                                                            /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return base.Render(renderContext); + return base.Render(renderContext, visualTree); } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs index 4c173925..ca19e248 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemHeader.cs @@ -27,8 +27,9 @@ public ControlNavigationItemHeader(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext.Request?.Culture, Text))) { diff --git a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs index 8cacb780..37186d94 100644 --- a/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlNavigationItemLink.cs @@ -27,10 +27,11 @@ public ControlNavigationItemLink(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var html = base.Render(renderContext); + var html = base.Render(renderContext, visualTree); if (NoWrap) { diff --git a/src/WebExpress.WebUI/WebControl/ControlPagination.cs b/src/WebExpress.WebUI/WebControl/ControlPagination.cs index 71b93a8f..a5d19934 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPagination.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPagination.cs @@ -51,6 +51,7 @@ // /// Convert to html. // /// // /// The context in which the control is rendered. +// /// < param name = "visualTree" > The visual tree representing the control's structure. // /// The control as html. // public override IHtmlNode Render(IRenderContext context) // { diff --git a/src/WebExpress.WebUI/WebControl/ControlPanel.cs b/src/WebExpress.WebUI/WebControl/ControlPanel.cs index 9c99594e..9f340d32 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanel.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanel.cs @@ -123,10 +123,11 @@ public virtual void Clear() /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementTextContentDiv(_content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs index dbdc98a3..4ba8e207 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCallout.cs @@ -37,8 +37,9 @@ public ControlPanelCallout(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { @@ -56,7 +57,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) }); } - html.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) + html.Add(new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Class = "callout-body" }); diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs index f24f86a7..738f643a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCard.cs @@ -51,8 +51,9 @@ public ControlPanelCard(string id = null, params IControl[] controls) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var content = Content; var html = new HtmlElementTextContentDiv() @@ -89,7 +90,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) content = headContent.Concat(Content); } - html.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(content.Select(x => x.Render(renderContext)).ToArray()) + html.Add(new HtmlElementTextContentDiv(new HtmlElementTextContentDiv(content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Class = "card-text" }) diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs index 67e4eeab..eb564426 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelCenter.cs @@ -23,10 +23,11 @@ public ControlPanelCenter(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var html = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs index 3e882e2f..0285e420 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFlexbox.cs @@ -59,8 +59,9 @@ public ControlPanelFlexbox(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { @@ -70,7 +71,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Add(Content.Select(x => x.Render(renderContext))); + html.Add(Content.Select(x => x.Render(renderContext, visualTree))); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs index 85c64a7c..fe6ecac9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelFooter.cs @@ -24,10 +24,11 @@ public ControlPanelFooter(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementSectionFooter(Content.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementSectionFooter(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs index 6078db75..465e8766 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelGrid.cs @@ -26,8 +26,9 @@ public ControlPanelGrid(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { @@ -39,7 +40,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) html.Add(new HtmlElementTextContentDiv ( - Content.Select(x => x.Render(renderContext)).ToArray() + Content.Select(x => x.Render(renderContext, visualTree)).ToArray() ) { Class = "row" diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs index 8f83b8ec..37eb92c9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelHeader.cs @@ -42,10 +42,11 @@ public ControlPanelHeader(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return new HtmlElementSectionHeader(Content.Select(x => x.Render(renderContext)).ToArray()) + return new HtmlElementSectionHeader(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs index d5a84689..c13ab7b3 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMain.cs @@ -24,10 +24,11 @@ public ControlPanelMain(string id = null, params IControl[] content) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var html = new HtmlElementSectionMain(Content.Select(x => x.Render(renderContext)).ToArray()) + var html = new HtmlElementSectionMain(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = GetClasses(), diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs index b6590c45..6bc9f3ff 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelMedia.cs @@ -44,8 +44,9 @@ public ControlPanelMedia(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var img = new HtmlElementMultimediaImg() { @@ -72,7 +73,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Class = "media-body" }; - body.Add(Content.Select(x => x.Render(renderContext))); + body.Add(Content.Select(x => x.Render(renderContext, visualTree))); var html = new HtmlElementTextContentDiv(img, body) { diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs index c05810c0..d7fe84a5 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelNavbar.cs @@ -23,8 +23,9 @@ public ControlPanelNavbar(string id = null, params IControl[] items) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementSectionNav() { @@ -34,7 +35,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Add(from x in Content select x?.Render(renderContext)); + html.Add(from x in Content select x?.Render(renderContext, visualTree)); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs index bf7803ec..81f84d02 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelSplit.cs @@ -1,6 +1,7 @@ ο»Ώusing System.Collections.Generic; using System.Linq; using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebUri; using WebExpress.WebUI.WebPage; namespace WebExpress.WebUI.WebControl @@ -120,10 +121,10 @@ public void RemovePanel2(IControl control) /// Initializes the form element. /// /// The context in which the control is rendered. - public virtual void Initialize(IRenderControlContext renderContext) + protected virtual void Initialize(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var contextPath = renderContext?.PageContext?.ApplicationContext?.ContextPath; - //renderContext.AddHeaderScriptLink(UriResource.Combine(contextPath, "/assets/js/split.min.js")); + visualTree.AddHeaderScriptLink(UriResource.Combine(contextPath, "/assets/js/split.min.js")); Border = new PropertyBorder(true); @@ -145,7 +146,7 @@ public virtual void Initialize(IRenderControlContext renderContext) init2 = 100 - Panel1InitialSize; } - renderContext.AddScript + visualTree.AddScript ( Id, @"Split(['#" + Id + "-p1', '#" + Id + @"-p2'], { sizes: [" + init1 + "," + init2 + @"], @@ -167,10 +168,11 @@ public virtual void Initialize(IRenderControlContext renderContext) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - Initialize(renderContext); + Initialize(renderContext, visualTree); var html = new HtmlElementTextContentDiv() { @@ -180,8 +182,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(renderContext)).ToArray()) { Id = $"{Id}-p1" }); - html.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(renderContext)).ToArray()) { Id = $"{Id}-p2" }); + html.Add(new HtmlElementTextContentDiv(Panel1.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = $"{Id}-p1" }); + html.Add(new HtmlElementTextContentDiv(Panel2.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = $"{Id}-p2" }); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs index 1b51c8e1..07379c7e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs +++ b/src/WebExpress.WebUI/WebControl/ControlPanelTool.cs @@ -28,11 +28,12 @@ public ControlPanelTool(string id = null, params Control[] items) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var dropDown = Tools.Render(renderContext); - var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext)).ToArray()); + var dropDown = Tools.Render(renderContext, visualTree); + var content = new HtmlElementTextContentDiv(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()); var html = new HtmlElementTextContentDiv(dropDown, content) { diff --git a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs index 6c7deefc..4fce8fea 100644 --- a/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlProgressBar.cs @@ -67,8 +67,9 @@ public ControlProgressBar(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (Format == TypeFormatProgress.Default) { diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs index 18f9559a..f1eec58b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButton.cs @@ -129,8 +129,9 @@ public void AddHeader(string text) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var button = new HtmlElementFieldButton() { @@ -152,7 +153,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -196,8 +197,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) x == null || x is ControlDropdownItemDivider || x is ControlLine ? new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } + x.Render(renderContext, visualTree) : + new HtmlElementTextContentLi(x.Render(renderContext, visualTree)) { Class = "dropdown-item" } ).ToArray() ) { @@ -206,7 +207,7 @@ x is ControlDropdownItemHeader ? var html = new HtmlElementTextContentDiv ( - Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(renderContext)) : button, + Modal != null && Modal.Type == TypeModal.Modal ? new HtmlList(button, Modal.Modal.Render(renderContext, visualTree)) : button, dropdownButton, dropdownElements ) diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs index b11113be..9907def6 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemDivider.cs @@ -21,8 +21,9 @@ public ControlSplitButtonItemDivider(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementTextContentDiv() { diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs index 9f2d7017..92a292f4 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemHeader.cs @@ -27,8 +27,9 @@ public ControlSplitButtonItemHeader(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { return new HtmlElementTextContentLi(new HtmlText(I18N.Translate(renderContext?.Request?.Culture, Text))) { diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs index 2aa50120..1b72ad65 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonItemLink.cs @@ -21,10 +21,11 @@ public ControlSplitButtonItemLink(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - return base.Render(renderContext); + return base.Render(renderContext, visualTree); } } } diff --git a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs index cb967ae9..fb99802e 100644 --- a/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlSplitButtonLink.cs @@ -37,8 +37,9 @@ public ControlSplitButtonLink(string id = null, params IControlSplitButtonItem[] /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var button = new HtmlElementTextSemanticsA() { @@ -63,7 +64,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -108,8 +109,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) x == null || x is ControlDropdownItemDivider || x is ControlLine ? new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "dropdown-item" } + x.Render(renderContext, visualTree) : + new HtmlElementTextContentLi(x.Render(renderContext, visualTree)) { Class = "dropdown-item" } ).ToArray() ) { @@ -118,7 +119,7 @@ x is ControlDropdownItemHeader ? var html = new HtmlElementTextContentDiv ( - Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(renderContext)) : button, + Modal != null && Modal.Type == TypeModal.Modal ? (IHtmlNode)new HtmlList(button, Modal.Modal.Render(renderContext, visualTree)) : button, dropdownButton, dropdownElements ) diff --git a/src/WebExpress.WebUI/WebControl/ControlTable.cs b/src/WebExpress.WebUI/WebControl/ControlTable.cs index a92fc24f..c1217e42 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTable.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTable.cs @@ -124,8 +124,9 @@ public void AddRows(IEnumerable rows) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { _columns.ForEach(x => x.Layout = ColumnLayout); var classes = Classes.ToList(); @@ -154,8 +155,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) Role = Role }; - html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(renderContext)).ToArray()); - html.Rows.AddRange(from x in Rows select x.Render(renderContext) as HtmlElementTableTr); + html.Columns = new HtmlElementTableTr(Columns.Select(x => x.Render(renderContext, visualTree)).ToArray()); + html.Rows.AddRange(from x in Rows select x.Render(renderContext, visualTree) as HtmlElementTableTr); return html; } diff --git a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs index b90ab3a9..ce61383b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableColumn.cs @@ -39,8 +39,9 @@ public ControlTableColumn(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var classes = Classes.ToList(); @@ -93,7 +94,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) diff --git a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs index 47163503..4fd4e02a 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTableRow.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTableRow.cs @@ -53,8 +53,9 @@ public void Remove(IControl cell) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { switch (Layout) { @@ -84,7 +85,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) break; } - return new HtmlElementTableTr(_cells.Select(c => new HtmlElementTableTd(c.Render(renderContext))).ToArray()) + return new HtmlElementTableTr(_cells.Select(c => new HtmlElementTableTd(c.Render(renderContext, visualTree))).ToArray()) { Id = Id, Class = string.Join(" ", Classes.Where(x => !string.IsNullOrWhiteSpace(x))), diff --git a/src/WebExpress.WebUI/WebControl/ControlTag.cs b/src/WebExpress.WebUI/WebControl/ControlTag.cs index aa12eade..d332145b 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTag.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTag.cs @@ -87,8 +87,9 @@ public void AddHeader(string text) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { if (Pill) { @@ -139,8 +140,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) x == null ? new HtmlElementTextContentLi() { Class = "dropdown-divider", Inline = true } : x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext).AddClass("dropdown-item")) { } + x.Render(renderContext, visualTree) : + new HtmlElementTextContentLi(x.Render(renderContext, visualTree).AddClass("dropdown-item")) { } ).ToArray() ) { diff --git a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs index bb08c27c..4a1b6e6c 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTagCloud.cs @@ -32,6 +32,7 @@ // /// Convert to html. // /// // /// The context in which the control is rendered. +// /// The visual tree representing the control's structure. // /// The control as html. // public override IHtmlNode Render(IRenderContext context) // { diff --git a/src/WebExpress.WebUI/WebControl/ControlText.cs b/src/WebExpress.WebUI/WebControl/ControlText.cs index 436478ed..c7e90865 100644 --- a/src/WebExpress.WebUI/WebControl/ControlText.cs +++ b/src/WebExpress.WebUI/WebControl/ControlText.cs @@ -59,8 +59,9 @@ public ControlText(string id = null) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var text = I18N.Translate(renderContext?.Request.Culture, Text); var html = default(HtmlElement); diff --git a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs index d304c041..7fc22674 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimeline.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimeline.cs @@ -49,6 +49,7 @@ // /// Convert to html. // /// // /// The context in which the control is rendered. +// /// The visual tree representing the control's structure. // /// The control as html. // public override IHtmlNode Render(IRenderContext context) // { diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs index 84fe52ef..2cca4cb9 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineComment.cs @@ -44,6 +44,7 @@ // /// Convert to html. // /// // /// The context in which the control is rendered. +// /// The visual tree representing the control's structure. // /// The control as html. // public override IHtmlNode Render(IRenderContext context) // { diff --git a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs index d390221b..22a0df2f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTimelineItem.cs @@ -70,6 +70,7 @@ // /// Convert to html. // /// // /// The context in which the control is rendered. +// /// The visual tree representing the control's structure. // /// The control as html. // public override IHtmlNode Render(IRenderContext context) // { diff --git a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs index cd0c6bcf..5b998c6d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlToolbar.cs +++ b/src/WebExpress.WebUI/WebControl/ControlToolbar.cs @@ -129,8 +129,9 @@ public void Remove(IControlToolbarItem item) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var html = new HtmlElementSectionNav() { @@ -150,8 +151,8 @@ public override IHtmlNode Render(IRenderControlContext renderContext) x == null || x is ControlDropdownItemDivider || x is ControlLine ? new HtmlElementTextContentLi() { Class = "divider", Inline = true } : x is ControlDropdownItemHeader ? - x.Render(renderContext) : - new HtmlElementTextContentLi(x.Render(renderContext)) { Class = "nav-item" } + x.Render(renderContext, visualTree) : + new HtmlElementTextContentLi(x.Render(renderContext, visualTree)) { Class = "nav-item" } ).ToArray() ) { diff --git a/src/WebExpress.WebUI/WebControl/ControlTree.cs b/src/WebExpress.WebUI/WebControl/ControlTree.cs index ed73bdbc..b8be099d 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTree.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTree.cs @@ -78,10 +78,11 @@ public void Remove(ControlTreeItem item) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var items = (from x in Nodes select x.Render(renderContext)).ToList(); + var items = (from x in Nodes select x.Render(renderContext, visualTree)).ToList(); switch (Layout) { @@ -102,7 +103,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (Layout == TypeLayoutTree.TreeView) { - renderContext.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); + visualTree.AddScript("treeview", @"var toggler = document.getElementsByClassName(""tree-treeview-angle""); for (var i = 0; i < toggler.length; i++) { toggler[i].addEventListener(""click"", function() { diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs index e229710f..82ebecb1 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItem.cs @@ -140,10 +140,11 @@ public void Remove(IControl control) /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { - var content = _content.Select(x => x.Render(renderContext)).ToArray(); + var content = _content.Select(x => x.Render(renderContext, visualTree)).ToArray(); var container = default(HtmlElementTextContentDiv); if (Layout == TypeLayoutTreeItem.TreeView) @@ -181,7 +182,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (_children.Count > 0) { - var children = _children.Select(x => x.Render(renderContext)).ToList(); + var children = _children.Select(x => x.Render(renderContext, visualTree)).ToList(); switch (Layout) { diff --git a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs index 02c7dc51..2c5e104f 100644 --- a/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs +++ b/src/WebExpress.WebUI/WebControl/ControlTreeItemLink.cs @@ -90,12 +90,13 @@ public string GetParams() /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - public override IHtmlNode Render(IRenderControlContext renderContext) + public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree) { var param = GetParams(); - var link = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext)).ToArray()) + var link = new HtmlElementTextSemanticsA(Content.Select(x => x.Render(renderContext, visualTree)).ToArray()) { Id = Id, Class = Css.Concatenate("link tree-link", Active == TypeActive.Active ? "tree-link-active" : ""), @@ -119,7 +120,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) PropertySpacing.Space.None ) : new PropertySpacingMargin(PropertySpacing.Space.None), VerticalAlignment = Icon.IsUserIcon ? TypeVerticalAlignment.TextBottom : TypeVerticalAlignment.Default - }.Render(renderContext)); + }.Render(renderContext, visualTree)); } if (!string.IsNullOrWhiteSpace(Text)) @@ -163,7 +164,7 @@ public override IHtmlNode Render(IRenderControlContext renderContext) if (Children.Count() > 0) { - var items = (from x in Children select x.Render(renderContext)).ToList(); + var items = (from x in Children select x.Render(renderContext, visualTree)).ToList(); var ul = new HtmlElementTextContentUl(items.ToArray()) { Class = Css.Concatenate(Layout switch diff --git a/src/WebExpress.WebUI/WebControl/IControl.cs b/src/WebExpress.WebUI/WebControl/IControl.cs index 67ff5fea..ffb56957 100644 --- a/src/WebExpress.WebUI/WebControl/IControl.cs +++ b/src/WebExpress.WebUI/WebControl/IControl.cs @@ -92,7 +92,8 @@ public interface IControl /// Convert the control to HTML. /// /// The context in which the control is rendered. + /// The visual tree representing the control's structure. /// An HTML node representing the rendered control. - IHtmlNode Render(IRenderControlContext renderContext); + IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree); } } diff --git a/src/WebExpress.WebUI/WebFragment/FragmentControlForm.cs b/src/WebExpress.WebUI/WebFragment/FragmentControlForm.cs new file mode 100644 index 00000000..488fca63 --- /dev/null +++ b/src/WebExpress.WebUI/WebFragment/FragmentControlForm.cs @@ -0,0 +1,35 @@ +ο»Ώusing System; +using WebExpress.WebCore.WebFragment; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.WebFragment +{ + /// + /// Represents a form control fragment that can display a form. + /// + public class FragmentControlForm : ControlForm, IFragmentControl + { + /// + /// Returns the context of the fragment. + /// + public IFragmentContext FragmentContext { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// The context of the fragment. + public FragmentControlForm(IFragmentContext fragmentContext) + : base(fragmentContext?.FragmentId?.ToString()) + { + FragmentContext = fragmentContext; + } + + /// + /// Releases all resources used by the fragment. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + } + } +} diff --git a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs index ebc93ec9..23dd20d6 100644 --- a/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs +++ b/src/WebExpress.WebUI/WebFragment/IFragmentControl.cs @@ -7,15 +7,16 @@ namespace WebExpress.WebUI.WebFragment /// /// Represents a fragment control interface. /// - public interface IFragmentControl : IFragment, IControl + public interface IFragmentControl : IFragment, IControl { } /// /// Represents a fragment interface with a generic type parameter. /// - /// The type of control that implements the IControl interface. - public interface IFragmentControl : IFragmentControl where T : class, IControl + /// The type of control that implements the IControl interface. + public interface IFragmentControl : IFragmentControl + where TControl : class, IControl { /// /// Gets the context of the fragment. diff --git a/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs b/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs index 677bc34e..78bd7acc 100644 --- a/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs +++ b/src/WebExpress.WebUI/WebPage/IRenderControlContext.cs @@ -7,17 +7,5 @@ namespace WebExpress.WebUI.WebPage /// public interface IRenderControlContext : IRenderContext { - /// - /// Adds or replaces a java script if it exists. - /// - /// The key. - /// The java script code. - void AddScript(string key, string code); - - /// - /// Adds a java script. - /// - /// The link of the java script file. - void AddScriptLink(string url); } } diff --git a/src/WebExpress.WebUI/WebPage/IVisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/IVisualTreeControl.cs new file mode 100644 index 00000000..b603eb09 --- /dev/null +++ b/src/WebExpress.WebUI/WebPage/IVisualTreeControl.cs @@ -0,0 +1,174 @@ +ο»Ώusing System.Collections.Generic; +using WebExpress.WebCore.WebHtml; +using WebExpress.WebCore.WebPage; +using WebExpress.WebUI.WebControl; + +namespace WebExpress.WebUI.WebPage +{ + /// + /// Represents a control that is part of the visual tree and implements the IVisualTree interface. + /// + public interface IVisualTreeControl : IVisualTree + { + /// + /// Returns the title of the html document. + /// + string Title { get; set; } + + /// + /// Returns the favicons. + /// + IEnumerable Favicons { get; } + + /// + /// Returns the internal stylesheet. + /// + IEnumerable Styles { get; } + + /// + /// Returns the links to the java script files to be used, which are inserted in the header. + /// + IEnumerable HeaderScriptLinks { get; } + + /// + /// Returns the links to the java script files to be used. + /// + IEnumerable ScriptLinks { get; } + + /// + /// Returns the links to the java script files to be used, which are inserted in the header. + /// + IEnumerable HeaderScripts { get; } + + /// + /// Returns the links to the java script files to be used. + /// + IReadOnlyDictionary Scripts { get; } + + /// + /// Returns the links to the css files to be used. + /// + IEnumerable CssLinks { get; } + + /// + /// Returns the meta information. + /// + IReadOnlyDictionary Meta { get; } + + /// + /// Returns the content. + /// + IEnumerable Content { get; } + + /// + /// Adds a favicon to the web application. + /// + /// The URL of the favicon. + /// The media type of the favicon. + void AddFavicon(string url, string mediatype); + + /// + /// Removes a favicon from the web application. + /// + /// The URL of the favicon to remove. + void RemoveFavicon(string url); + + /// + /// Adds one or more styles to the head. + /// + /// The styles to add. + void AddStyle(params string[] styles); + + /// + /// Removes a style from the head. + /// + /// The style to remove. + void RemoveStyle(string style); + + /// + /// Adds one or more URLs to the list of header script links. + /// + /// The URLs of the script to add. + void AddHeaderScriptLink(params string[] urls); + + /// + /// Removes a URL from the list of header script links. + /// + /// The URL of the script to remove. + void RemoveHeaderScriptLink(string url); + + /// + /// Adds one or more URLs to the list of script links. + /// + /// The URLs of the script to add. + void AddScriptLink(params string[] urls); + + /// + /// Removes a URL from the list of script links. + /// + /// The URL of the script to remove. + void RemoveScriptLink(string url); + + /// + /// Adds one or more URLs to the list of header scripts. + /// + /// The URLs of the script to add. + void AddHeaderScript(params string[] urls); + + /// + /// Removes a URL from the list of header scripts. + /// + /// The URL of the script to remove. + void RemoveHeaderScript(string url); + + /// + /// Adds a script to the collection. If a script with the same identifier already exists, it will be overwritten. + /// + /// The identifier of the script. + /// The script content. + void AddScript(string id, string script); + + /// + /// Removes a script from the collection. + /// + /// The identifier of the script to remove. + void RemoveScript(string id); + + /// + /// Adds one or more URLs to the list of CSS links. + /// + /// The URLs of the CSS file to add. + void AddCssLink(params string[] urls); + + /// + /// Removes all CSS links that match the specified URL. + /// + /// The URL of the CSS link to remove. + void RemoveCssLink(string url); + + /// + /// Adds a meta tag to the collection. If a meta tag with the same name already exists, it will be overwritten. + /// + /// The name of the meta tag. + /// The content of the meta tag. + void AddMeta(string name, string content); + + /// + /// Removes a meta tag from the collection. + /// + /// The name of the meta tag to remove. + void RemoveMeta(string name); + + /// + /// Adds one or more controls to the content of the page. + /// + /// The controls to add to the content. + void AddContent(params IControl[] controls); + + /// + /// Removes a control from the content of the page. + /// + /// The control to remove from the content. + void RemoveContent(IControl control); + } +} diff --git a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs index ebdc7eef..a6cc4764 100644 --- a/src/WebExpress.WebUI/WebPage/RenderControlContext.cs +++ b/src/WebExpress.WebUI/WebPage/RenderControlContext.cs @@ -9,23 +9,6 @@ namespace WebExpress.WebUI.WebPage /// public class RenderControlContext : RenderContext, IRenderControlContext { - /// - /// Adds or replaces a java script if it exists. - /// - /// The key. - /// The java script code. - void IRenderControlContext.AddScript(string key, string code) - { - } - - /// - /// Adds a java script. - /// - /// The link of the java script file. - void IRenderControlContext.AddScriptLink(string url) - { - } - /// /// Initializes a new instance of the class. /// diff --git a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs index ba0ed06e..59986308 100644 --- a/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs +++ b/src/WebExpress.WebUI/WebPage/VisualTreeControl.cs @@ -12,7 +12,7 @@ namespace WebExpress.WebUI.WebPage /// /// The content design of a page is realized by controls. /// - public class VisualTreeControl : IVisualTree + public class VisualTreeControl : IVisualTreeControl { private readonly IComponentHub _componentHub; private readonly List _favicons = []; @@ -227,7 +227,10 @@ public virtual void RemoveHeaderScript(string url) /// The script content. public virtual void AddScript(string id, string script) { - _scripts[id] = script; + if (id != null) + { + _scripts[id] = script; + } } /// From 94feb09d071fed1c0031a1d0426bf3c9846081c1 Mon Sep 17 00:00:00 2001 From: Rene Schwarzer Date: Mon, 6 Jan 2025 11:45:50 +0100 Subject: [PATCH 39/59] general improvements and bug fixes --- .../UnitTestControlFormItemButtonReset.cs | 262 + .../UnitTestControlFormItemButtonSubmit.cs | 84 +- .../Assets/css/fontawesome.min.css | 8 +- src/WebExpress.WebUI/Assets/css/solid.css | 28 +- .../Assets/fonts/fa-brands-400.eot | Bin 136822 -> 0 bytes .../Assets/fonts/fa-brands-400.svg | 3717 ------------ .../Assets/fonts/fa-brands-400.ttf | Bin 136516 -> 210792 bytes .../Assets/fonts/fa-brands-400.woff | Bin 92136 -> 0 bytes .../Assets/fonts/fa-brands-400.woff2 | Bin 78460 -> 118684 bytes .../Assets/fonts/fa-regular-400.eot | Bin 34350 -> 0 bytes .../Assets/fonts/fa-regular-400.svg | 801 --- .../Assets/fonts/fa-regular-400.ttf | Bin 34052 -> 68064 bytes .../Assets/fonts/fa-regular-400.woff | Bin 16772 -> 0 bytes .../Assets/fonts/fa-regular-400.woff2 | Bin 13548 -> 25472 bytes .../Assets/fonts/fa-solid-900.eot | Bin 204814 -> 0 bytes .../Assets/fonts/fa-solid-900.svg | 5028 ----------------- .../Assets/fonts/fa-solid-900.ttf | Bin 204528 -> 426112 bytes .../Assets/fonts/fa-solid-900.woff | Bin 104280 -> 0 bytes .../Assets/fonts/fa-solid-900.woff2 | Bin 80300 -> 158220 bytes .../Assets/fonts/fa-v4compatibility.ttf | Bin 0 -> 10836 bytes .../Assets/fonts/fa-v4compatibility.woff2 | Bin 0 -> 4796 bytes src/WebExpress.WebUI/Internationalization/de | 1 + src/WebExpress.WebUI/Internationalization/en | 1 + .../WebControl/ControlForm.cs | 100 +- .../WebControl/ControlFormItemButtonReset.cs | 24 + .../WebControl/ControlFormItemButtonSubmit.cs | 1 - .../WebControl/ControlFormItemGroupColumn.cs | 4 +- .../ControlFormItemGroupColumnHorizontal.cs | 4 +- .../ControlFormItemGroupColumnMix.cs | 4 +- .../ControlFormItemGroupColumnVertical.cs | 4 +- .../ControlFormItemGroupHorizontal.cs | 4 +- .../WebControl/ControlFormItemGroupMix.cs | 4 +- .../ControlFormItemGroupVertical.cs | 4 +- src/WebExpress.WebUI/WebControl/TypeIcon.cs | 8 +- src/WebExpress.WebUI/WebExpress.WebUI.csproj | 19 +- .../SectionFormFooterPreferences.cs | 11 + .../WebSection/SectionFormFooterPrimary.cs | 11 + .../WebSection/SectionFormFooterSecondary.cs | 11 + .../SectionFormHeaderPreferences.cs | 11 + .../WebSection/SectionFormHeaderPrimary.cs | 11 + .../WebSection/SectionFormHeaderSecondary.cs | 11 + 41 files changed, 530 insertions(+), 9646 deletions(-) create mode 100644 src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonReset.cs delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-brands-400.eot delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-brands-400.svg delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-brands-400.woff delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-regular-400.eot delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-regular-400.svg delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-regular-400.woff delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-solid-900.eot delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-solid-900.svg delete mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-solid-900.woff create mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-v4compatibility.ttf create mode 100644 src/WebExpress.WebUI/Assets/fonts/fa-v4compatibility.woff2 create mode 100644 src/WebExpress.WebUI/WebControl/ControlFormItemButtonReset.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormFooterPreferences.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormFooterPrimary.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormFooterSecondary.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormHeaderPreferences.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormHeaderPrimary.cs create mode 100644 src/WebExpress.WebUI/WebSection/SectionFormHeaderSecondary.cs diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonReset.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonReset.cs new file mode 100644 index 00000000..0af98173 --- /dev/null +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonReset.cs @@ -0,0 +1,262 @@ +ο»Ώusing WebExpress.WebUI.Test.Fixture; +using WebExpress.WebUI.WebControl; +using WebExpress.WebUI.WebPage; + +namespace WebExpress.WebUI.Test.WebControl +{ + /// + /// Tests the form reset button control. + /// + [Collection("NonParallelTests")] + public class UnitTestControlFormItemButtonReset + { + /// + /// Tests the id property of the form submit button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("id", @"")] + public void Id(string id, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset(id) + { + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the text property of the form reset button control. + /// + [Theory] + [InlineData(null, @"")] + [InlineData("abc", @"")] + public void Text(string text, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Text = text + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the size property of the form reset button control. + /// + [Theory] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] + public void Size(TypeSizeButton size, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Size = size + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the backgroundcolor property of the form reset button control. + /// + [Theory] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.White, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] + public void BackgroundColor(TypeColorBackground color, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + BackgroundColor = new PropertyColorBackground(color) + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the color property of the form reset button control. + /// + [Theory] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + [InlineData(TypeColorButton.Light, @"")] + public void Color(TypeColorButton color, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the outline property of the form reset button control. + /// + [Theory] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + [InlineData(true, TypeColorButton.Light, @"")] + public void Outline(bool outline, TypeColorButton color, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Outline = outline, + Color = new PropertyColorButton(color) + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the block property of the form reset button control. + /// + [Theory] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] + public void Block(TypeBlockButton block, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Block = block + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the icon property of the form reset button control. + /// + [Theory] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] + public void Icon(TypeIcon icon, string expected) + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control = new ControlFormItemButtonReset() + { + Icon = new PropertyIcon(icon) + }; + + // test execution + var html = control.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(expected, html); + } + + /// + /// Tests the add function of the form reset button control. + /// + [Fact] + public void Add() + { + // preconditions + var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock(); + var form = new ControlForm(); + var context = new RenderControlFormContext(UnitTestControlFixture.CrerateRenderContextMock(), form); + var visualTree = new VisualTreeControl(componentHub, context.PageContext); + var control1 = new ControlFormItemButtonReset(null, new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + var control2 = new ControlFormItemButtonReset(null, [new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + var control3 = new ControlFormItemButtonReset(null, new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]).ToArray()); + var control4 = new ControlFormItemButtonReset(null); + var control5 = new ControlFormItemButtonReset(null); + var control6 = new ControlFormItemButtonReset(null); + + // test execution + control4.Add(new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }); + control5.Add([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }]); + control6.Add(new List([new ControlIcon() { Icon = new PropertyIcon(TypeIcon.Star) }])); + + var html1 = control1.Render(context, visualTree); + var html2 = control2.Render(context, visualTree); + var html3 = control3.Render(context, visualTree); + var html4 = control4.Render(context, visualTree); + var html5 = control5.Render(context, visualTree); + var html6 = control6.Render(context, visualTree); + + AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html3.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html4.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html5.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html6.Trim()); + } + } +} diff --git a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs index 000493f7..4d720983 100644 --- a/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs +++ b/src/WebExpress.WebUI.Test/WebControl/UnitTestControlFormItemButtonSubmit.cs @@ -14,8 +14,8 @@ public class UnitTestControlFormItemButtonSubmit /// Tests the id property of the form submit button control. /// [Theory] - [InlineData(null, @"")] - [InlineData("id", @"")] + [InlineData(null, @"")] + [InlineData("id", @"")] public void Id(string id, string expected) { // preconditions @@ -37,8 +37,8 @@ public void Id(string id, string expected) /// Tests the text property of the form submit button control. /// [Theory] - [InlineData(null, @"")] - [InlineData("abc", @"")] + [InlineData(null, @"")] + [InlineData("abc", @"")] public void Text(string text, string expected) { // preconditions @@ -61,9 +61,9 @@ public void Text(string text, string expected) /// Tests the size property of the form submit button control. /// [Theory] - [InlineData(TypeSizeButton.Default, @"")] - [InlineData(TypeSizeButton.Small, @"")] - [InlineData(TypeSizeButton.Large, @"")] + [InlineData(TypeSizeButton.Default, @"")] + [InlineData(TypeSizeButton.Small, @"")] + [InlineData(TypeSizeButton.Large, @"")] public void Size(TypeSizeButton size, string expected) { // preconditions @@ -86,15 +86,15 @@ public void Size(TypeSizeButton size, string expected) /// Tests the backgroundcolor property of the form submit button control. /// [Theory] - [InlineData(TypeColorBackground.Default, @"")] - [InlineData(TypeColorBackground.Primary, @"")] - [InlineData(TypeColorBackground.Secondary, @"")] - [InlineData(TypeColorBackground.Warning, @"")] - [InlineData(TypeColorBackground.Danger, @"")] - [InlineData(TypeColorBackground.Dark, @"")] - [InlineData(TypeColorBackground.Light, @"")] - [InlineData(TypeColorBackground.White, @"")] - [InlineData(TypeColorBackground.Transparent, @"")] + [InlineData(TypeColorBackground.Default, @"")] + [InlineData(TypeColorBackground.Primary, @"")] + [InlineData(TypeColorBackground.Secondary, @"")] + [InlineData(TypeColorBackground.Warning, @"")] + [InlineData(TypeColorBackground.Danger, @"")] + [InlineData(TypeColorBackground.Dark, @"")] + [InlineData(TypeColorBackground.Light, @"")] + [InlineData(TypeColorBackground.White, @"")] + [InlineData(TypeColorBackground.Transparent, @"")] public void BackgroundColor(TypeColorBackground color, string expected) { // preconditions @@ -114,16 +114,16 @@ public void BackgroundColor(TypeColorBackground color, string expected) } /// - /// Tests the outline property of the form submit button control. + /// Tests the color property of the form submit button control. /// [Theory] - [InlineData(TypeColorButton.Default, @"")] - [InlineData(TypeColorButton.Primary, @"")] - [InlineData(TypeColorButton.Secondary, @"")] - [InlineData(TypeColorButton.Warning, @"")] - [InlineData(TypeColorButton.Danger, @"")] - [InlineData(TypeColorButton.Dark, @"")] - [InlineData(TypeColorButton.Light, @"")] + [InlineData(TypeColorButton.Default, @"")] + [InlineData(TypeColorButton.Primary, @"")] + [InlineData(TypeColorButton.Secondary, @"")] + [InlineData(TypeColorButton.Warning, @"")] + [InlineData(TypeColorButton.Danger, @"")] + [InlineData(TypeColorButton.Dark, @"")] + [InlineData(TypeColorButton.Light, @"")] public void Color(TypeColorButton color, string expected) { // preconditions @@ -146,14 +146,14 @@ public void Color(TypeColorButton color, string expected) /// Tests the outline property of the form submit button control. /// [Theory] - [InlineData(false, TypeColorButton.Default, @"")] - [InlineData(true, TypeColorButton.Default, @"")] - [InlineData(true, TypeColorButton.Primary, @"")] - [InlineData(true, TypeColorButton.Secondary, @"")] - [InlineData(true, TypeColorButton.Warning, @"")] - [InlineData(true, TypeColorButton.Danger, @"")] - [InlineData(true, TypeColorButton.Dark, @"")] - [InlineData(true, TypeColorButton.Light, @"")] + [InlineData(false, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Default, @"")] + [InlineData(true, TypeColorButton.Primary, @"")] + [InlineData(true, TypeColorButton.Secondary, @"")] + [InlineData(true, TypeColorButton.Warning, @"")] + [InlineData(true, TypeColorButton.Danger, @"")] + [InlineData(true, TypeColorButton.Dark, @"")] + [InlineData(true, TypeColorButton.Light, @"")] public void Outline(bool outline, TypeColorButton color, string expected) { // preconditions @@ -177,8 +177,8 @@ public void Outline(bool outline, TypeColorButton color, string expected) /// Tests the block property of the form submit button control. /// [Theory] - [InlineData(TypeBlockButton.None, @"")] - [InlineData(TypeBlockButton.Block, @"")] + [InlineData(TypeBlockButton.None, @"")] + [InlineData(TypeBlockButton.Block, @"")] public void Block(TypeBlockButton block, string expected) { // preconditions @@ -201,8 +201,8 @@ public void Block(TypeBlockButton block, string expected) /// Tests the icon property of the form submit button control. /// [Theory] - [InlineData(TypeIcon.None, @"")] - [InlineData(TypeIcon.Star, @"")] + [InlineData(TypeIcon.None, @"")] + [InlineData(TypeIcon.Star, @"")] public void Icon(TypeIcon icon, string expected) { // preconditions @@ -251,12 +251,12 @@ public void Add() var html5 = control5.Render(context, visualTree); var html6 = control6.Render(context, visualTree); - AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); - AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); - AssertExtensions.EqualWithPlaceholders(@"", html3.Trim()); - AssertExtensions.EqualWithPlaceholders(@"", html4.Trim()); - AssertExtensions.EqualWithPlaceholders(@"", html5.Trim()); - AssertExtensions.EqualWithPlaceholders(@"", html6.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html1.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html2.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html3.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html4.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html5.Trim()); + AssertExtensions.EqualWithPlaceholders(@"", html6.Trim()); } } } diff --git a/src/WebExpress.WebUI/Assets/css/fontawesome.min.css b/src/WebExpress.WebUI/Assets/css/fontawesome.min.css index 8e36e25a..4e07e306 100644 --- a/src/WebExpress.WebUI/Assets/css/fontawesome.min.css +++ b/src/WebExpress.WebUI/Assets/css/fontawesome.min.css @@ -1,5 +1,9 @@ /*! - * Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. */ -.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file +.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-regular,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-brands:before,.fa-regular:before,.fa-solid:before,.fa:before,.fab:before,.far:before,.fas:before{content:var(--fa)}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{animation-name:fa-fade;animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{animation-name:fa-beat-fade;animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{animation-name:fa-shake;animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-shake,.fa-spin{animation-delay:var(--fa-animation-delay,0s);animation-direction:var(--fa-animation-direction,normal)}.fa-spin{animation-name:fa-spin;animation-duration:var(--fa-animation-duration,2s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,linear)}.fa-spin-reverse{--fa-animation-direction:reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction,normal);animation-duration:var(--fa-animation-duration,1s);animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-timing-function:var(--fa-animation-timing,steps(8))}@media (prefers-reduced-motion:reduce){.fa-beat,.fa-beat-fade,.fa-bounce,.fa-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale,1.25))}}@keyframes fa-bounce{0%{transform:scale(1) translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x,1.1),var(--fa-bounce-start-scale-y,.9)) translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x,.9),var(--fa-bounce-jump-scale-y,1.1)) translateY(var(--fa-bounce-height,-.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x,1.05),var(--fa-bounce-land-scale-y,.95)) translateY(0)}57%{transform:scale(1) translateY(var(--fa-bounce-rebound,-.125em))}64%{transform:scale(1) translateY(0)}to{transform:scale(1) translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity,.4)}}@keyframes fa-beat-fade{0%,to{opacity:var(--fa-beat-fade-opacity,.4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale,1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x,0),var(--fa-flip-y,1),var(--fa-flip-z,0),var(--fa-flip-angle,-180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}8%,24%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}40%,to{transform:rotate(0deg)}}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle,0))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index,auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse,#fff)} + +.fa-0{--fa:"\30"}.fa-1{--fa:"\31"}.fa-2{--fa:"\32"}.fa-3{--fa:"\33"}.fa-4{--fa:"\34"}.fa-5{--fa:"\35"}.fa-6{--fa:"\36"}.fa-7{--fa:"\37"}.fa-8{--fa:"\38"}.fa-9{--fa:"\39"}.fa-fill-drip{--fa:"\f576"}.fa-arrows-to-circle{--fa:"\e4bd"}.fa-chevron-circle-right,.fa-circle-chevron-right{--fa:"\f138"}.fa-at{--fa:"\40"}.fa-trash-alt,.fa-trash-can{--fa:"\f2ed"}.fa-text-height{--fa:"\f034"}.fa-user-times,.fa-user-xmark{--fa:"\f235"}.fa-stethoscope{--fa:"\f0f1"}.fa-comment-alt,.fa-message{--fa:"\f27a"}.fa-info{--fa:"\f129"}.fa-compress-alt,.fa-down-left-and-up-right-to-center{--fa:"\f422"}.fa-explosion{--fa:"\e4e9"}.fa-file-alt,.fa-file-lines,.fa-file-text{--fa:"\f15c"}.fa-wave-square{--fa:"\f83e"}.fa-ring{--fa:"\f70b"}.fa-building-un{--fa:"\e4d9"}.fa-dice-three{--fa:"\f527"}.fa-calendar-alt,.fa-calendar-days{--fa:"\f073"}.fa-anchor-circle-check{--fa:"\e4aa"}.fa-building-circle-arrow-right{--fa:"\e4d1"}.fa-volleyball,.fa-volleyball-ball{--fa:"\f45f"}.fa-arrows-up-to-line{--fa:"\e4c2"}.fa-sort-desc,.fa-sort-down{--fa:"\f0dd"}.fa-circle-minus,.fa-minus-circle{--fa:"\f056"}.fa-door-open{--fa:"\f52b"}.fa-right-from-bracket,.fa-sign-out-alt{--fa:"\f2f5"}.fa-atom{--fa:"\f5d2"}.fa-soap{--fa:"\e06e"}.fa-heart-music-camera-bolt,.fa-icons{--fa:"\f86d"}.fa-microphone-alt-slash,.fa-microphone-lines-slash{--fa:"\f539"}.fa-bridge-circle-check{--fa:"\e4c9"}.fa-pump-medical{--fa:"\e06a"}.fa-fingerprint{--fa:"\f577"}.fa-hand-point-right{--fa:"\f0a4"}.fa-magnifying-glass-location,.fa-search-location{--fa:"\f689"}.fa-forward-step,.fa-step-forward{--fa:"\f051"}.fa-face-smile-beam,.fa-smile-beam{--fa:"\f5b8"}.fa-flag-checkered{--fa:"\f11e"}.fa-football,.fa-football-ball{--fa:"\f44e"}.fa-school-circle-exclamation{--fa:"\e56c"}.fa-crop{--fa:"\f125"}.fa-angle-double-down,.fa-angles-down{--fa:"\f103"}.fa-users-rectangle{--fa:"\e594"}.fa-people-roof{--fa:"\e537"}.fa-people-line{--fa:"\e534"}.fa-beer,.fa-beer-mug-empty{--fa:"\f0fc"}.fa-diagram-predecessor{--fa:"\e477"}.fa-arrow-up-long,.fa-long-arrow-up{--fa:"\f176"}.fa-burn,.fa-fire-flame-simple{--fa:"\f46a"}.fa-male,.fa-person{--fa:"\f183"}.fa-laptop{--fa:"\f109"}.fa-file-csv{--fa:"\f6dd"}.fa-menorah{--fa:"\f676"}.fa-truck-plane{--fa:"\e58f"}.fa-record-vinyl{--fa:"\f8d9"}.fa-face-grin-stars,.fa-grin-stars{--fa:"\f587"}.fa-bong{--fa:"\f55c"}.fa-pastafarianism,.fa-spaghetti-monster-flying{--fa:"\f67b"}.fa-arrow-down-up-across-line{--fa:"\e4af"}.fa-spoon,.fa-utensil-spoon{--fa:"\f2e5"}.fa-jar-wheat{--fa:"\e517"}.fa-envelopes-bulk,.fa-mail-bulk{--fa:"\f674"}.fa-file-circle-exclamation{--fa:"\e4eb"}.fa-circle-h,.fa-hospital-symbol{--fa:"\f47e"}.fa-pager{--fa:"\f815"}.fa-address-book,.fa-contact-book{--fa:"\f2b9"}.fa-strikethrough{--fa:"\f0cc"}.fa-k{--fa:"\4b"}.fa-landmark-flag{--fa:"\e51c"}.fa-pencil,.fa-pencil-alt{--fa:"\f303"}.fa-backward{--fa:"\f04a"}.fa-caret-right{--fa:"\f0da"}.fa-comments{--fa:"\f086"}.fa-file-clipboard,.fa-paste{--fa:"\f0ea"}.fa-code-pull-request{--fa:"\e13c"}.fa-clipboard-list{--fa:"\f46d"}.fa-truck-loading,.fa-truck-ramp-box{--fa:"\f4de"}.fa-user-check{--fa:"\f4fc"}.fa-vial-virus{--fa:"\e597"}.fa-sheet-plastic{--fa:"\e571"}.fa-blog{--fa:"\f781"}.fa-user-ninja{--fa:"\f504"}.fa-person-arrow-up-from-line{--fa:"\e539"}.fa-scroll-torah,.fa-torah{--fa:"\f6a0"}.fa-broom-ball,.fa-quidditch,.fa-quidditch-broom-ball{--fa:"\f458"}.fa-toggle-off{--fa:"\f204"}.fa-archive,.fa-box-archive{--fa:"\f187"}.fa-person-drowning{--fa:"\e545"}.fa-arrow-down-9-1,.fa-sort-numeric-desc,.fa-sort-numeric-down-alt{--fa:"\f886"}.fa-face-grin-tongue-squint,.fa-grin-tongue-squint{--fa:"\f58a"}.fa-spray-can{--fa:"\f5bd"}.fa-truck-monster{--fa:"\f63b"}.fa-w{--fa:"\57"}.fa-earth-africa,.fa-globe-africa{--fa:"\f57c"}.fa-rainbow{--fa:"\f75b"}.fa-circle-notch{--fa:"\f1ce"}.fa-tablet-alt,.fa-tablet-screen-button{--fa:"\f3fa"}.fa-paw{--fa:"\f1b0"}.fa-cloud{--fa:"\f0c2"}.fa-trowel-bricks{--fa:"\e58a"}.fa-face-flushed,.fa-flushed{--fa:"\f579"}.fa-hospital-user{--fa:"\f80d"}.fa-tent-arrow-left-right{--fa:"\e57f"}.fa-gavel,.fa-legal{--fa:"\f0e3"}.fa-binoculars{--fa:"\f1e5"}.fa-microphone-slash{--fa:"\f131"}.fa-box-tissue{--fa:"\e05b"}.fa-motorcycle{--fa:"\f21c"}.fa-bell-concierge,.fa-concierge-bell{--fa:"\f562"}.fa-pen-ruler,.fa-pencil-ruler{--fa:"\f5ae"}.fa-people-arrows,.fa-people-arrows-left-right{--fa:"\e068"}.fa-mars-and-venus-burst{--fa:"\e523"}.fa-caret-square-right,.fa-square-caret-right{--fa:"\f152"}.fa-cut,.fa-scissors{--fa:"\f0c4"}.fa-sun-plant-wilt{--fa:"\e57a"}.fa-toilets-portable{--fa:"\e584"}.fa-hockey-puck{--fa:"\f453"}.fa-table{--fa:"\f0ce"}.fa-magnifying-glass-arrow-right{--fa:"\e521"}.fa-digital-tachograph,.fa-tachograph-digital{--fa:"\f566"}.fa-users-slash{--fa:"\e073"}.fa-clover{--fa:"\e139"}.fa-mail-reply,.fa-reply{--fa:"\f3e5"}.fa-star-and-crescent{--fa:"\f699"}.fa-house-fire{--fa:"\e50c"}.fa-minus-square,.fa-square-minus{--fa:"\f146"}.fa-helicopter{--fa:"\f533"}.fa-compass{--fa:"\f14e"}.fa-caret-square-down,.fa-square-caret-down{--fa:"\f150"}.fa-file-circle-question{--fa:"\e4ef"}.fa-laptop-code{--fa:"\f5fc"}.fa-swatchbook{--fa:"\f5c3"}.fa-prescription-bottle{--fa:"\f485"}.fa-bars,.fa-navicon{--fa:"\f0c9"}.fa-people-group{--fa:"\e533"}.fa-hourglass-3,.fa-hourglass-end{--fa:"\f253"}.fa-heart-broken,.fa-heart-crack{--fa:"\f7a9"}.fa-external-link-square-alt,.fa-square-up-right{--fa:"\f360"}.fa-face-kiss-beam,.fa-kiss-beam{--fa:"\f597"}.fa-film{--fa:"\f008"}.fa-ruler-horizontal{--fa:"\f547"}.fa-people-robbery{--fa:"\e536"}.fa-lightbulb{--fa:"\f0eb"}.fa-caret-left{--fa:"\f0d9"}.fa-circle-exclamation,.fa-exclamation-circle{--fa:"\f06a"}.fa-school-circle-xmark{--fa:"\e56d"}.fa-arrow-right-from-bracket,.fa-sign-out{--fa:"\f08b"}.fa-chevron-circle-down,.fa-circle-chevron-down{--fa:"\f13a"}.fa-unlock-alt,.fa-unlock-keyhole{--fa:"\f13e"}.fa-cloud-showers-heavy{--fa:"\f740"}.fa-headphones-alt,.fa-headphones-simple{--fa:"\f58f"}.fa-sitemap{--fa:"\f0e8"}.fa-circle-dollar-to-slot,.fa-donate{--fa:"\f4b9"}.fa-memory{--fa:"\f538"}.fa-road-spikes{--fa:"\e568"}.fa-fire-burner{--fa:"\e4f1"}.fa-flag{--fa:"\f024"}.fa-hanukiah{--fa:"\f6e6"}.fa-feather{--fa:"\f52d"}.fa-volume-down,.fa-volume-low{--fa:"\f027"}.fa-comment-slash{--fa:"\f4b3"}.fa-cloud-sun-rain{--fa:"\f743"}.fa-compress{--fa:"\f066"}.fa-wheat-alt,.fa-wheat-awn{--fa:"\e2cd"}.fa-ankh{--fa:"\f644"}.fa-hands-holding-child{--fa:"\e4fa"}.fa-asterisk{--fa:"\2a"}.fa-check-square,.fa-square-check{--fa:"\f14a"}.fa-peseta-sign{--fa:"\e221"}.fa-header,.fa-heading{--fa:"\f1dc"}.fa-ghost{--fa:"\f6e2"}.fa-list,.fa-list-squares{--fa:"\f03a"}.fa-phone-square-alt,.fa-square-phone-flip{--fa:"\f87b"}.fa-cart-plus{--fa:"\f217"}.fa-gamepad{--fa:"\f11b"}.fa-circle-dot,.fa-dot-circle{--fa:"\f192"}.fa-dizzy,.fa-face-dizzy{--fa:"\f567"}.fa-egg{--fa:"\f7fb"}.fa-house-medical-circle-xmark{--fa:"\e513"}.fa-campground{--fa:"\f6bb"}.fa-folder-plus{--fa:"\f65e"}.fa-futbol,.fa-futbol-ball,.fa-soccer-ball{--fa:"\f1e3"}.fa-paint-brush,.fa-paintbrush{--fa:"\f1fc"}.fa-lock{--fa:"\f023"}.fa-gas-pump{--fa:"\f52f"}.fa-hot-tub,.fa-hot-tub-person{--fa:"\f593"}.fa-map-location,.fa-map-marked{--fa:"\f59f"}.fa-house-flood-water{--fa:"\e50e"}.fa-tree{--fa:"\f1bb"}.fa-bridge-lock{--fa:"\e4cc"}.fa-sack-dollar{--fa:"\f81d"}.fa-edit,.fa-pen-to-square{--fa:"\f044"}.fa-car-side{--fa:"\f5e4"}.fa-share-alt,.fa-share-nodes{--fa:"\f1e0"}.fa-heart-circle-minus{--fa:"\e4ff"}.fa-hourglass-2,.fa-hourglass-half{--fa:"\f252"}.fa-microscope{--fa:"\f610"}.fa-sink{--fa:"\e06d"}.fa-bag-shopping,.fa-shopping-bag{--fa:"\f290"}.fa-arrow-down-z-a,.fa-sort-alpha-desc,.fa-sort-alpha-down-alt{--fa:"\f881"}.fa-mitten{--fa:"\f7b5"}.fa-person-rays{--fa:"\e54d"}.fa-users{--fa:"\f0c0"}.fa-eye-slash{--fa:"\f070"}.fa-flask-vial{--fa:"\e4f3"}.fa-hand,.fa-hand-paper{--fa:"\f256"}.fa-om{--fa:"\f679"}.fa-worm{--fa:"\e599"}.fa-house-circle-xmark{--fa:"\e50b"}.fa-plug{--fa:"\f1e6"}.fa-chevron-up{--fa:"\f077"}.fa-hand-spock{--fa:"\f259"}.fa-stopwatch{--fa:"\f2f2"}.fa-face-kiss,.fa-kiss{--fa:"\f596"}.fa-bridge-circle-xmark{--fa:"\e4cb"}.fa-face-grin-tongue,.fa-grin-tongue{--fa:"\f589"}.fa-chess-bishop{--fa:"\f43a"}.fa-face-grin-wink,.fa-grin-wink{--fa:"\f58c"}.fa-deaf,.fa-deafness,.fa-ear-deaf,.fa-hard-of-hearing{--fa:"\f2a4"}.fa-road-circle-check{--fa:"\e564"}.fa-dice-five{--fa:"\f523"}.fa-rss-square,.fa-square-rss{--fa:"\f143"}.fa-land-mine-on{--fa:"\e51b"}.fa-i-cursor{--fa:"\f246"}.fa-stamp{--fa:"\f5bf"}.fa-stairs{--fa:"\e289"}.fa-i{--fa:"\49"}.fa-hryvnia,.fa-hryvnia-sign{--fa:"\f6f2"}.fa-pills{--fa:"\f484"}.fa-face-grin-wide,.fa-grin-alt{--fa:"\f581"}.fa-tooth{--fa:"\f5c9"}.fa-v{--fa:"\56"}.fa-bangladeshi-taka-sign{--fa:"\e2e6"}.fa-bicycle{--fa:"\f206"}.fa-rod-asclepius,.fa-rod-snake,.fa-staff-aesculapius,.fa-staff-snake{--fa:"\e579"}.fa-head-side-cough-slash{--fa:"\e062"}.fa-ambulance,.fa-truck-medical{--fa:"\f0f9"}.fa-wheat-awn-circle-exclamation{--fa:"\e598"}.fa-snowman{--fa:"\f7d0"}.fa-mortar-pestle{--fa:"\f5a7"}.fa-road-barrier{--fa:"\e562"}.fa-school{--fa:"\f549"}.fa-igloo{--fa:"\f7ae"}.fa-joint{--fa:"\f595"}.fa-angle-right{--fa:"\f105"}.fa-horse{--fa:"\f6f0"}.fa-q{--fa:"\51"}.fa-g{--fa:"\47"}.fa-notes-medical{--fa:"\f481"}.fa-temperature-2,.fa-temperature-half,.fa-thermometer-2,.fa-thermometer-half{--fa:"\f2c9"}.fa-dong-sign{--fa:"\e169"}.fa-capsules{--fa:"\f46b"}.fa-poo-bolt,.fa-poo-storm{--fa:"\f75a"}.fa-face-frown-open,.fa-frown-open{--fa:"\f57a"}.fa-hand-point-up{--fa:"\f0a6"}.fa-money-bill{--fa:"\f0d6"}.fa-bookmark{--fa:"\f02e"}.fa-align-justify{--fa:"\f039"}.fa-umbrella-beach{--fa:"\f5ca"}.fa-helmet-un{--fa:"\e503"}.fa-bullseye{--fa:"\f140"}.fa-bacon{--fa:"\f7e5"}.fa-hand-point-down{--fa:"\f0a7"}.fa-arrow-up-from-bracket{--fa:"\e09a"}.fa-folder,.fa-folder-blank{--fa:"\f07b"}.fa-file-medical-alt,.fa-file-waveform{--fa:"\f478"}.fa-radiation{--fa:"\f7b9"}.fa-chart-simple{--fa:"\e473"}.fa-mars-stroke{--fa:"\f229"}.fa-vial{--fa:"\f492"}.fa-dashboard,.fa-gauge,.fa-gauge-med,.fa-tachometer-alt-average{--fa:"\f624"}.fa-magic-wand-sparkles,.fa-wand-magic-sparkles{--fa:"\e2ca"}.fa-e{--fa:"\45"}.fa-pen-alt,.fa-pen-clip{--fa:"\f305"}.fa-bridge-circle-exclamation{--fa:"\e4ca"}.fa-user{--fa:"\f007"}.fa-school-circle-check{--fa:"\e56b"}.fa-dumpster{--fa:"\f793"}.fa-shuttle-van,.fa-van-shuttle{--fa:"\f5b6"}.fa-building-user{--fa:"\e4da"}.fa-caret-square-left,.fa-square-caret-left{--fa:"\f191"}.fa-highlighter{--fa:"\f591"}.fa-key{--fa:"\f084"}.fa-bullhorn{--fa:"\f0a1"}.fa-globe{--fa:"\f0ac"}.fa-synagogue{--fa:"\f69b"}.fa-person-half-dress{--fa:"\e548"}.fa-road-bridge{--fa:"\e563"}.fa-location-arrow{--fa:"\f124"}.fa-c{--fa:"\43"}.fa-tablet-button{--fa:"\f10a"}.fa-building-lock{--fa:"\e4d6"}.fa-pizza-slice{--fa:"\f818"}.fa-money-bill-wave{--fa:"\f53a"}.fa-area-chart,.fa-chart-area{--fa:"\f1fe"}.fa-house-flag{--fa:"\e50d"}.fa-person-circle-minus{--fa:"\e540"}.fa-ban,.fa-cancel{--fa:"\f05e"}.fa-camera-rotate{--fa:"\e0d8"}.fa-air-freshener,.fa-spray-can-sparkles{--fa:"\f5d0"}.fa-star{--fa:"\f005"}.fa-repeat{--fa:"\f363"}.fa-cross{--fa:"\f654"}.fa-box{--fa:"\f466"}.fa-venus-mars{--fa:"\f228"}.fa-arrow-pointer,.fa-mouse-pointer{--fa:"\f245"}.fa-expand-arrows-alt,.fa-maximize{--fa:"\f31e"}.fa-charging-station{--fa:"\f5e7"}.fa-shapes,.fa-triangle-circle-square{--fa:"\f61f"}.fa-random,.fa-shuffle{--fa:"\f074"}.fa-person-running,.fa-running{--fa:"\f70c"}.fa-mobile-retro{--fa:"\e527"}.fa-grip-lines-vertical{--fa:"\f7a5"}.fa-spider{--fa:"\f717"}.fa-hands-bound{--fa:"\e4f9"}.fa-file-invoice-dollar{--fa:"\f571"}.fa-plane-circle-exclamation{--fa:"\e556"}.fa-x-ray{--fa:"\f497"}.fa-spell-check{--fa:"\f891"}.fa-slash{--fa:"\f715"}.fa-computer-mouse,.fa-mouse{--fa:"\f8cc"}.fa-arrow-right-to-bracket,.fa-sign-in{--fa:"\f090"}.fa-shop-slash,.fa-store-alt-slash{--fa:"\e070"}.fa-server{--fa:"\f233"}.fa-virus-covid-slash{--fa:"\e4a9"}.fa-shop-lock{--fa:"\e4a5"}.fa-hourglass-1,.fa-hourglass-start{--fa:"\f251"}.fa-blender-phone{--fa:"\f6b6"}.fa-building-wheat{--fa:"\e4db"}.fa-person-breastfeeding{--fa:"\e53a"}.fa-right-to-bracket,.fa-sign-in-alt{--fa:"\f2f6"}.fa-venus{--fa:"\f221"}.fa-passport{--fa:"\f5ab"}.fa-thumb-tack-slash,.fa-thumbtack-slash{--fa:"\e68f"}.fa-heart-pulse,.fa-heartbeat{--fa:"\f21e"}.fa-people-carry,.fa-people-carry-box{--fa:"\f4ce"}.fa-temperature-high{--fa:"\f769"}.fa-microchip{--fa:"\f2db"}.fa-crown{--fa:"\f521"}.fa-weight-hanging{--fa:"\f5cd"}.fa-xmarks-lines{--fa:"\e59a"}.fa-file-prescription{--fa:"\f572"}.fa-weight,.fa-weight-scale{--fa:"\f496"}.fa-user-friends,.fa-user-group{--fa:"\f500"}.fa-arrow-up-a-z,.fa-sort-alpha-up{--fa:"\f15e"}.fa-chess-knight{--fa:"\f441"}.fa-face-laugh-squint,.fa-laugh-squint{--fa:"\f59b"}.fa-wheelchair{--fa:"\f193"}.fa-arrow-circle-up,.fa-circle-arrow-up{--fa:"\f0aa"}.fa-toggle-on{--fa:"\f205"}.fa-person-walking,.fa-walking{--fa:"\f554"}.fa-l{--fa:"\4c"}.fa-fire{--fa:"\f06d"}.fa-bed-pulse,.fa-procedures{--fa:"\f487"}.fa-shuttle-space,.fa-space-shuttle{--fa:"\f197"}.fa-face-laugh,.fa-laugh{--fa:"\f599"}.fa-folder-open{--fa:"\f07c"}.fa-heart-circle-plus{--fa:"\e500"}.fa-code-fork{--fa:"\e13b"}.fa-city{--fa:"\f64f"}.fa-microphone-alt,.fa-microphone-lines{--fa:"\f3c9"}.fa-pepper-hot{--fa:"\f816"}.fa-unlock{--fa:"\f09c"}.fa-colon-sign{--fa:"\e140"}.fa-headset{--fa:"\f590"}.fa-store-slash{--fa:"\e071"}.fa-road-circle-xmark{--fa:"\e566"}.fa-user-minus{--fa:"\f503"}.fa-mars-stroke-up,.fa-mars-stroke-v{--fa:"\f22a"}.fa-champagne-glasses,.fa-glass-cheers{--fa:"\f79f"}.fa-clipboard{--fa:"\f328"}.fa-house-circle-exclamation{--fa:"\e50a"}.fa-file-arrow-up,.fa-file-upload{--fa:"\f574"}.fa-wifi,.fa-wifi-3,.fa-wifi-strong{--fa:"\f1eb"}.fa-bath,.fa-bathtub{--fa:"\f2cd"}.fa-underline{--fa:"\f0cd"}.fa-user-edit,.fa-user-pen{--fa:"\f4ff"}.fa-signature{--fa:"\f5b7"}.fa-stroopwafel{--fa:"\f551"}.fa-bold{--fa:"\f032"}.fa-anchor-lock{--fa:"\e4ad"}.fa-building-ngo{--fa:"\e4d7"}.fa-manat-sign{--fa:"\e1d5"}.fa-not-equal{--fa:"\f53e"}.fa-border-style,.fa-border-top-left{--fa:"\f853"}.fa-map-location-dot,.fa-map-marked-alt{--fa:"\f5a0"}.fa-jedi{--fa:"\f669"}.fa-poll,.fa-square-poll-vertical{--fa:"\f681"}.fa-mug-hot{--fa:"\f7b6"}.fa-battery-car,.fa-car-battery{--fa:"\f5df"}.fa-gift{--fa:"\f06b"}.fa-dice-two{--fa:"\f528"}.fa-chess-queen{--fa:"\f445"}.fa-glasses{--fa:"\f530"}.fa-chess-board{--fa:"\f43c"}.fa-building-circle-check{--fa:"\e4d2"}.fa-person-chalkboard{--fa:"\e53d"}.fa-mars-stroke-h,.fa-mars-stroke-right{--fa:"\f22b"}.fa-hand-back-fist,.fa-hand-rock{--fa:"\f255"}.fa-caret-square-up,.fa-square-caret-up{--fa:"\f151"}.fa-cloud-showers-water{--fa:"\e4e4"}.fa-bar-chart,.fa-chart-bar{--fa:"\f080"}.fa-hands-bubbles,.fa-hands-wash{--fa:"\e05e"}.fa-less-than-equal{--fa:"\f537"}.fa-train{--fa:"\f238"}.fa-eye-low-vision,.fa-low-vision{--fa:"\f2a8"}.fa-crow{--fa:"\f520"}.fa-sailboat{--fa:"\e445"}.fa-window-restore{--fa:"\f2d2"}.fa-plus-square,.fa-square-plus{--fa:"\f0fe"}.fa-torii-gate{--fa:"\f6a1"}.fa-frog{--fa:"\f52e"}.fa-bucket{--fa:"\e4cf"}.fa-image{--fa:"\f03e"}.fa-microphone{--fa:"\f130"}.fa-cow{--fa:"\f6c8"}.fa-caret-up{--fa:"\f0d8"}.fa-screwdriver{--fa:"\f54a"}.fa-folder-closed{--fa:"\e185"}.fa-house-tsunami{--fa:"\e515"}.fa-square-nfi{--fa:"\e576"}.fa-arrow-up-from-ground-water{--fa:"\e4b5"}.fa-glass-martini-alt,.fa-martini-glass{--fa:"\f57b"}.fa-square-binary{--fa:"\e69b"}.fa-rotate-back,.fa-rotate-backward,.fa-rotate-left,.fa-undo-alt{--fa:"\f2ea"}.fa-columns,.fa-table-columns{--fa:"\f0db"}.fa-lemon{--fa:"\f094"}.fa-head-side-mask{--fa:"\e063"}.fa-handshake{--fa:"\f2b5"}.fa-gem{--fa:"\f3a5"}.fa-dolly,.fa-dolly-box{--fa:"\f472"}.fa-smoking{--fa:"\f48d"}.fa-compress-arrows-alt,.fa-minimize{--fa:"\f78c"}.fa-monument{--fa:"\f5a6"}.fa-snowplow{--fa:"\f7d2"}.fa-angle-double-right,.fa-angles-right{--fa:"\f101"}.fa-cannabis{--fa:"\f55f"}.fa-circle-play,.fa-play-circle{--fa:"\f144"}.fa-tablets{--fa:"\f490"}.fa-ethernet{--fa:"\f796"}.fa-eur,.fa-euro,.fa-euro-sign{--fa:"\f153"}.fa-chair{--fa:"\f6c0"}.fa-check-circle,.fa-circle-check{--fa:"\f058"}.fa-circle-stop,.fa-stop-circle{--fa:"\f28d"}.fa-compass-drafting,.fa-drafting-compass{--fa:"\f568"}.fa-plate-wheat{--fa:"\e55a"}.fa-icicles{--fa:"\f7ad"}.fa-person-shelter{--fa:"\e54f"}.fa-neuter{--fa:"\f22c"}.fa-id-badge{--fa:"\f2c1"}.fa-marker{--fa:"\f5a1"}.fa-face-laugh-beam,.fa-laugh-beam{--fa:"\f59a"}.fa-helicopter-symbol{--fa:"\e502"}.fa-universal-access{--fa:"\f29a"}.fa-chevron-circle-up,.fa-circle-chevron-up{--fa:"\f139"}.fa-lari-sign{--fa:"\e1c8"}.fa-volcano{--fa:"\f770"}.fa-person-walking-dashed-line-arrow-right{--fa:"\e553"}.fa-gbp,.fa-pound-sign,.fa-sterling-sign{--fa:"\f154"}.fa-viruses{--fa:"\e076"}.fa-square-person-confined{--fa:"\e577"}.fa-user-tie{--fa:"\f508"}.fa-arrow-down-long,.fa-long-arrow-down{--fa:"\f175"}.fa-tent-arrow-down-to-line{--fa:"\e57e"}.fa-certificate{--fa:"\f0a3"}.fa-mail-reply-all,.fa-reply-all{--fa:"\f122"}.fa-suitcase{--fa:"\f0f2"}.fa-person-skating,.fa-skating{--fa:"\f7c5"}.fa-filter-circle-dollar,.fa-funnel-dollar{--fa:"\f662"}.fa-camera-retro{--fa:"\f083"}.fa-arrow-circle-down,.fa-circle-arrow-down{--fa:"\f0ab"}.fa-arrow-right-to-file,.fa-file-import{--fa:"\f56f"}.fa-external-link-square,.fa-square-arrow-up-right{--fa:"\f14c"}.fa-box-open{--fa:"\f49e"}.fa-scroll{--fa:"\f70e"}.fa-spa{--fa:"\f5bb"}.fa-location-pin-lock{--fa:"\e51f"}.fa-pause{--fa:"\f04c"}.fa-hill-avalanche{--fa:"\e507"}.fa-temperature-0,.fa-temperature-empty,.fa-thermometer-0,.fa-thermometer-empty{--fa:"\f2cb"}.fa-bomb{--fa:"\f1e2"}.fa-registered{--fa:"\f25d"}.fa-address-card,.fa-contact-card,.fa-vcard{--fa:"\f2bb"}.fa-balance-scale-right,.fa-scale-unbalanced-flip{--fa:"\f516"}.fa-subscript{--fa:"\f12c"}.fa-diamond-turn-right,.fa-directions{--fa:"\f5eb"}.fa-burst{--fa:"\e4dc"}.fa-house-laptop,.fa-laptop-house{--fa:"\e066"}.fa-face-tired,.fa-tired{--fa:"\f5c8"}.fa-money-bills{--fa:"\e1f3"}.fa-smog{--fa:"\f75f"}.fa-crutch{--fa:"\f7f7"}.fa-cloud-arrow-up,.fa-cloud-upload,.fa-cloud-upload-alt{--fa:"\f0ee"}.fa-palette{--fa:"\f53f"}.fa-arrows-turn-right{--fa:"\e4c0"}.fa-vest{--fa:"\e085"}.fa-ferry{--fa:"\e4ea"}.fa-arrows-down-to-people{--fa:"\e4b9"}.fa-seedling,.fa-sprout{--fa:"\f4d8"}.fa-arrows-alt-h,.fa-left-right{--fa:"\f337"}.fa-boxes-packing{--fa:"\e4c7"}.fa-arrow-circle-left,.fa-circle-arrow-left{--fa:"\f0a8"}.fa-group-arrows-rotate{--fa:"\e4f6"}.fa-bowl-food{--fa:"\e4c6"}.fa-candy-cane{--fa:"\f786"}.fa-arrow-down-wide-short,.fa-sort-amount-asc,.fa-sort-amount-down{--fa:"\f160"}.fa-cloud-bolt,.fa-thunderstorm{--fa:"\f76c"}.fa-remove-format,.fa-text-slash{--fa:"\f87d"}.fa-face-smile-wink,.fa-smile-wink{--fa:"\f4da"}.fa-file-word{--fa:"\f1c2"}.fa-file-powerpoint{--fa:"\f1c4"}.fa-arrows-h,.fa-arrows-left-right{--fa:"\f07e"}.fa-house-lock{--fa:"\e510"}.fa-cloud-arrow-down,.fa-cloud-download,.fa-cloud-download-alt{--fa:"\f0ed"}.fa-children{--fa:"\e4e1"}.fa-blackboard,.fa-chalkboard{--fa:"\f51b"}.fa-user-alt-slash,.fa-user-large-slash{--fa:"\f4fa"}.fa-envelope-open{--fa:"\f2b6"}.fa-handshake-alt-slash,.fa-handshake-simple-slash{--fa:"\e05f"}.fa-mattress-pillow{--fa:"\e525"}.fa-guarani-sign{--fa:"\e19a"}.fa-arrows-rotate,.fa-refresh,.fa-sync{--fa:"\f021"}.fa-fire-extinguisher{--fa:"\f134"}.fa-cruzeiro-sign{--fa:"\e152"}.fa-greater-than-equal{--fa:"\f532"}.fa-shield-alt,.fa-shield-halved{--fa:"\f3ed"}.fa-atlas,.fa-book-atlas{--fa:"\f558"}.fa-virus{--fa:"\e074"}.fa-envelope-circle-check{--fa:"\e4e8"}.fa-layer-group{--fa:"\f5fd"}.fa-arrows-to-dot{--fa:"\e4be"}.fa-archway{--fa:"\f557"}.fa-heart-circle-check{--fa:"\e4fd"}.fa-house-chimney-crack,.fa-house-damage{--fa:"\f6f1"}.fa-file-archive,.fa-file-zipper{--fa:"\f1c6"}.fa-square{--fa:"\f0c8"}.fa-glass-martini,.fa-martini-glass-empty{--fa:"\f000"}.fa-couch{--fa:"\f4b8"}.fa-cedi-sign{--fa:"\e0df"}.fa-italic{--fa:"\f033"}.fa-table-cells-column-lock{--fa:"\e678"}.fa-church{--fa:"\f51d"}.fa-comments-dollar{--fa:"\f653"}.fa-democrat{--fa:"\f747"}.fa-z{--fa:"\5a"}.fa-person-skiing,.fa-skiing{--fa:"\f7c9"}.fa-road-lock{--fa:"\e567"}.fa-a{--fa:"\41"}.fa-temperature-arrow-down,.fa-temperature-down{--fa:"\e03f"}.fa-feather-alt,.fa-feather-pointed{--fa:"\f56b"}.fa-p{--fa:"\50"}.fa-snowflake{--fa:"\f2dc"}.fa-newspaper{--fa:"\f1ea"}.fa-ad,.fa-rectangle-ad{--fa:"\f641"}.fa-arrow-circle-right,.fa-circle-arrow-right{--fa:"\f0a9"}.fa-filter-circle-xmark{--fa:"\e17b"}.fa-locust{--fa:"\e520"}.fa-sort,.fa-unsorted{--fa:"\f0dc"}.fa-list-1-2,.fa-list-numeric,.fa-list-ol{--fa:"\f0cb"}.fa-person-dress-burst{--fa:"\e544"}.fa-money-check-alt,.fa-money-check-dollar{--fa:"\f53d"}.fa-vector-square{--fa:"\f5cb"}.fa-bread-slice{--fa:"\f7ec"}.fa-language{--fa:"\f1ab"}.fa-face-kiss-wink-heart,.fa-kiss-wink-heart{--fa:"\f598"}.fa-filter{--fa:"\f0b0"}.fa-question{--fa:"\3f"}.fa-file-signature{--fa:"\f573"}.fa-arrows-alt,.fa-up-down-left-right{--fa:"\f0b2"}.fa-house-chimney-user{--fa:"\e065"}.fa-hand-holding-heart{--fa:"\f4be"}.fa-puzzle-piece{--fa:"\f12e"}.fa-money-check{--fa:"\f53c"}.fa-star-half-alt,.fa-star-half-stroke{--fa:"\f5c0"}.fa-code{--fa:"\f121"}.fa-glass-whiskey,.fa-whiskey-glass{--fa:"\f7a0"}.fa-building-circle-exclamation{--fa:"\e4d3"}.fa-magnifying-glass-chart{--fa:"\e522"}.fa-arrow-up-right-from-square,.fa-external-link{--fa:"\f08e"}.fa-cubes-stacked{--fa:"\e4e6"}.fa-krw,.fa-won,.fa-won-sign{--fa:"\f159"}.fa-virus-covid{--fa:"\e4a8"}.fa-austral-sign{--fa:"\e0a9"}.fa-f{--fa:"\46"}.fa-leaf{--fa:"\f06c"}.fa-road{--fa:"\f018"}.fa-cab,.fa-taxi{--fa:"\f1ba"}.fa-person-circle-plus{--fa:"\e541"}.fa-chart-pie,.fa-pie-chart{--fa:"\f200"}.fa-bolt-lightning{--fa:"\e0b7"}.fa-sack-xmark{--fa:"\e56a"}.fa-file-excel{--fa:"\f1c3"}.fa-file-contract{--fa:"\f56c"}.fa-fish-fins{--fa:"\e4f2"}.fa-building-flag{--fa:"\e4d5"}.fa-face-grin-beam,.fa-grin-beam{--fa:"\f582"}.fa-object-ungroup{--fa:"\f248"}.fa-poop{--fa:"\f619"}.fa-location-pin,.fa-map-marker{--fa:"\f041"}.fa-kaaba{--fa:"\f66b"}.fa-toilet-paper{--fa:"\f71e"}.fa-hard-hat,.fa-hat-hard,.fa-helmet-safety{--fa:"\f807"}.fa-eject{--fa:"\f052"}.fa-arrow-alt-circle-right,.fa-circle-right{--fa:"\f35a"}.fa-plane-circle-check{--fa:"\e555"}.fa-face-rolling-eyes,.fa-meh-rolling-eyes{--fa:"\f5a5"}.fa-object-group{--fa:"\f247"}.fa-chart-line,.fa-line-chart{--fa:"\f201"}.fa-mask-ventilator{--fa:"\e524"}.fa-arrow-right{--fa:"\f061"}.fa-map-signs,.fa-signs-post{--fa:"\f277"}.fa-cash-register{--fa:"\f788"}.fa-person-circle-question{--fa:"\e542"}.fa-h{--fa:"\48"}.fa-tarp{--fa:"\e57b"}.fa-screwdriver-wrench,.fa-tools{--fa:"\f7d9"}.fa-arrows-to-eye{--fa:"\e4bf"}.fa-plug-circle-bolt{--fa:"\e55b"}.fa-heart{--fa:"\f004"}.fa-mars-and-venus{--fa:"\f224"}.fa-home-user,.fa-house-user{--fa:"\e1b0"}.fa-dumpster-fire{--fa:"\f794"}.fa-house-crack{--fa:"\e3b1"}.fa-cocktail,.fa-martini-glass-citrus{--fa:"\f561"}.fa-face-surprise,.fa-surprise{--fa:"\f5c2"}.fa-bottle-water{--fa:"\e4c5"}.fa-circle-pause,.fa-pause-circle{--fa:"\f28b"}.fa-toilet-paper-slash{--fa:"\e072"}.fa-apple-alt,.fa-apple-whole{--fa:"\f5d1"}.fa-kitchen-set{--fa:"\e51a"}.fa-r{--fa:"\52"}.fa-temperature-1,.fa-temperature-quarter,.fa-thermometer-1,.fa-thermometer-quarter{--fa:"\f2ca"}.fa-cube{--fa:"\f1b2"}.fa-bitcoin-sign{--fa:"\e0b4"}.fa-shield-dog{--fa:"\e573"}.fa-solar-panel{--fa:"\f5ba"}.fa-lock-open{--fa:"\f3c1"}.fa-elevator{--fa:"\e16d"}.fa-money-bill-transfer{--fa:"\e528"}.fa-money-bill-trend-up{--fa:"\e529"}.fa-house-flood-water-circle-arrow-right{--fa:"\e50f"}.fa-poll-h,.fa-square-poll-horizontal{--fa:"\f682"}.fa-circle{--fa:"\f111"}.fa-backward-fast,.fa-fast-backward{--fa:"\f049"}.fa-recycle{--fa:"\f1b8"}.fa-user-astronaut{--fa:"\f4fb"}.fa-plane-slash{--fa:"\e069"}.fa-trademark{--fa:"\f25c"}.fa-basketball,.fa-basketball-ball{--fa:"\f434"}.fa-satellite-dish{--fa:"\f7c0"}.fa-arrow-alt-circle-up,.fa-circle-up{--fa:"\f35b"}.fa-mobile-alt,.fa-mobile-screen-button{--fa:"\f3cd"}.fa-volume-high,.fa-volume-up{--fa:"\f028"}.fa-users-rays{--fa:"\e593"}.fa-wallet{--fa:"\f555"}.fa-clipboard-check{--fa:"\f46c"}.fa-file-audio{--fa:"\f1c7"}.fa-burger,.fa-hamburger{--fa:"\f805"}.fa-wrench{--fa:"\f0ad"}.fa-bugs{--fa:"\e4d0"}.fa-rupee,.fa-rupee-sign{--fa:"\f156"}.fa-file-image{--fa:"\f1c5"}.fa-circle-question,.fa-question-circle{--fa:"\f059"}.fa-plane-departure{--fa:"\f5b0"}.fa-handshake-slash{--fa:"\e060"}.fa-book-bookmark{--fa:"\e0bb"}.fa-code-branch{--fa:"\f126"}.fa-hat-cowboy{--fa:"\f8c0"}.fa-bridge{--fa:"\e4c8"}.fa-phone-alt,.fa-phone-flip{--fa:"\f879"}.fa-truck-front{--fa:"\e2b7"}.fa-cat{--fa:"\f6be"}.fa-anchor-circle-exclamation{--fa:"\e4ab"}.fa-truck-field{--fa:"\e58d"}.fa-route{--fa:"\f4d7"}.fa-clipboard-question{--fa:"\e4e3"}.fa-panorama{--fa:"\e209"}.fa-comment-medical{--fa:"\f7f5"}.fa-teeth-open{--fa:"\f62f"}.fa-file-circle-minus{--fa:"\e4ed"}.fa-tags{--fa:"\f02c"}.fa-wine-glass{--fa:"\f4e3"}.fa-fast-forward,.fa-forward-fast{--fa:"\f050"}.fa-face-meh-blank,.fa-meh-blank{--fa:"\f5a4"}.fa-parking,.fa-square-parking{--fa:"\f540"}.fa-house-signal{--fa:"\e012"}.fa-bars-progress,.fa-tasks-alt{--fa:"\f828"}.fa-faucet-drip{--fa:"\e006"}.fa-cart-flatbed,.fa-dolly-flatbed{--fa:"\f474"}.fa-ban-smoking,.fa-smoking-ban{--fa:"\f54d"}.fa-terminal{--fa:"\f120"}.fa-mobile-button{--fa:"\f10b"}.fa-house-medical-flag{--fa:"\e514"}.fa-basket-shopping,.fa-shopping-basket{--fa:"\f291"}.fa-tape{--fa:"\f4db"}.fa-bus-alt,.fa-bus-simple{--fa:"\f55e"}.fa-eye{--fa:"\f06e"}.fa-face-sad-cry,.fa-sad-cry{--fa:"\f5b3"}.fa-audio-description{--fa:"\f29e"}.fa-person-military-to-person{--fa:"\e54c"}.fa-file-shield{--fa:"\e4f0"}.fa-user-slash{--fa:"\f506"}.fa-pen{--fa:"\f304"}.fa-tower-observation{--fa:"\e586"}.fa-file-code{--fa:"\f1c9"}.fa-signal,.fa-signal-5,.fa-signal-perfect{--fa:"\f012"}.fa-bus{--fa:"\f207"}.fa-heart-circle-xmark{--fa:"\e501"}.fa-home-lg,.fa-house-chimney{--fa:"\e3af"}.fa-window-maximize{--fa:"\f2d0"}.fa-face-frown,.fa-frown{--fa:"\f119"}.fa-prescription{--fa:"\f5b1"}.fa-shop,.fa-store-alt{--fa:"\f54f"}.fa-floppy-disk,.fa-save{--fa:"\f0c7"}.fa-vihara{--fa:"\f6a7"}.fa-balance-scale-left,.fa-scale-unbalanced{--fa:"\f515"}.fa-sort-asc,.fa-sort-up{--fa:"\f0de"}.fa-comment-dots,.fa-commenting{--fa:"\f4ad"}.fa-plant-wilt{--fa:"\e5aa"}.fa-diamond{--fa:"\f219"}.fa-face-grin-squint,.fa-grin-squint{--fa:"\f585"}.fa-hand-holding-dollar,.fa-hand-holding-usd{--fa:"\f4c0"}.fa-chart-diagram{--fa:"\e695"}.fa-bacterium{--fa:"\e05a"}.fa-hand-pointer{--fa:"\f25a"}.fa-drum-steelpan{--fa:"\f56a"}.fa-hand-scissors{--fa:"\f257"}.fa-hands-praying,.fa-praying-hands{--fa:"\f684"}.fa-arrow-right-rotate,.fa-arrow-rotate-forward,.fa-arrow-rotate-right,.fa-redo{--fa:"\f01e"}.fa-biohazard{--fa:"\f780"}.fa-location,.fa-location-crosshairs{--fa:"\f601"}.fa-mars-double{--fa:"\f227"}.fa-child-dress{--fa:"\e59c"}.fa-users-between-lines{--fa:"\e591"}.fa-lungs-virus{--fa:"\e067"}.fa-face-grin-tears,.fa-grin-tears{--fa:"\f588"}.fa-phone{--fa:"\f095"}.fa-calendar-times,.fa-calendar-xmark{--fa:"\f273"}.fa-child-reaching{--fa:"\e59d"}.fa-head-side-virus{--fa:"\e064"}.fa-user-cog,.fa-user-gear{--fa:"\f4fe"}.fa-arrow-up-1-9,.fa-sort-numeric-up{--fa:"\f163"}.fa-door-closed{--fa:"\f52a"}.fa-shield-virus{--fa:"\e06c"}.fa-dice-six{--fa:"\f526"}.fa-mosquito-net{--fa:"\e52c"}.fa-file-fragment{--fa:"\e697"}.fa-bridge-water{--fa:"\e4ce"}.fa-person-booth{--fa:"\f756"}.fa-text-width{--fa:"\f035"}.fa-hat-wizard{--fa:"\f6e8"}.fa-pen-fancy{--fa:"\f5ac"}.fa-digging,.fa-person-digging{--fa:"\f85e"}.fa-trash{--fa:"\f1f8"}.fa-gauge-simple,.fa-gauge-simple-med,.fa-tachometer-average{--fa:"\f629"}.fa-book-medical{--fa:"\f7e6"}.fa-poo{--fa:"\f2fe"}.fa-quote-right,.fa-quote-right-alt{--fa:"\f10e"}.fa-shirt,.fa-t-shirt,.fa-tshirt{--fa:"\f553"}.fa-cubes{--fa:"\f1b3"}.fa-divide{--fa:"\f529"}.fa-tenge,.fa-tenge-sign{--fa:"\f7d7"}.fa-headphones{--fa:"\f025"}.fa-hands-holding{--fa:"\f4c2"}.fa-hands-clapping{--fa:"\e1a8"}.fa-republican{--fa:"\f75e"}.fa-arrow-left{--fa:"\f060"}.fa-person-circle-xmark{--fa:"\e543"}.fa-ruler{--fa:"\f545"}.fa-align-left{--fa:"\f036"}.fa-dice-d6{--fa:"\f6d1"}.fa-restroom{--fa:"\f7bd"}.fa-j{--fa:"\4a"}.fa-users-viewfinder{--fa:"\e595"}.fa-file-video{--fa:"\f1c8"}.fa-external-link-alt,.fa-up-right-from-square{--fa:"\f35d"}.fa-table-cells,.fa-th{--fa:"\f00a"}.fa-file-pdf{--fa:"\f1c1"}.fa-bible,.fa-book-bible{--fa:"\f647"}.fa-o{--fa:"\4f"}.fa-medkit,.fa-suitcase-medical{--fa:"\f0fa"}.fa-user-secret{--fa:"\f21b"}.fa-otter{--fa:"\f700"}.fa-female,.fa-person-dress{--fa:"\f182"}.fa-comment-dollar{--fa:"\f651"}.fa-briefcase-clock,.fa-business-time{--fa:"\f64a"}.fa-table-cells-large,.fa-th-large{--fa:"\f009"}.fa-book-tanakh,.fa-tanakh{--fa:"\f827"}.fa-phone-volume,.fa-volume-control-phone{--fa:"\f2a0"}.fa-hat-cowboy-side{--fa:"\f8c1"}.fa-clipboard-user{--fa:"\f7f3"}.fa-child{--fa:"\f1ae"}.fa-lira-sign{--fa:"\f195"}.fa-satellite{--fa:"\f7bf"}.fa-plane-lock{--fa:"\e558"}.fa-tag{--fa:"\f02b"}.fa-comment{--fa:"\f075"}.fa-birthday-cake,.fa-cake,.fa-cake-candles{--fa:"\f1fd"}.fa-envelope{--fa:"\f0e0"}.fa-angle-double-up,.fa-angles-up{--fa:"\f102"}.fa-paperclip{--fa:"\f0c6"}.fa-arrow-right-to-city{--fa:"\e4b3"}.fa-ribbon{--fa:"\f4d6"}.fa-lungs{--fa:"\f604"}.fa-arrow-up-9-1,.fa-sort-numeric-up-alt{--fa:"\f887"}.fa-litecoin-sign{--fa:"\e1d3"}.fa-border-none{--fa:"\f850"}.fa-circle-nodes{--fa:"\e4e2"}.fa-parachute-box{--fa:"\f4cd"}.fa-indent{--fa:"\f03c"}.fa-truck-field-un{--fa:"\e58e"}.fa-hourglass,.fa-hourglass-empty{--fa:"\f254"}.fa-mountain{--fa:"\f6fc"}.fa-user-doctor,.fa-user-md{--fa:"\f0f0"}.fa-circle-info,.fa-info-circle{--fa:"\f05a"}.fa-cloud-meatball{--fa:"\f73b"}.fa-camera,.fa-camera-alt{--fa:"\f030"}.fa-square-virus{--fa:"\e578"}.fa-meteor{--fa:"\f753"}.fa-car-on{--fa:"\e4dd"}.fa-sleigh{--fa:"\f7cc"}.fa-arrow-down-1-9,.fa-sort-numeric-asc,.fa-sort-numeric-down{--fa:"\f162"}.fa-hand-holding-droplet,.fa-hand-holding-water{--fa:"\f4c1"}.fa-water{--fa:"\f773"}.fa-calendar-check{--fa:"\f274"}.fa-braille{--fa:"\f2a1"}.fa-prescription-bottle-alt,.fa-prescription-bottle-medical{--fa:"\f486"}.fa-landmark{--fa:"\f66f"}.fa-truck{--fa:"\f0d1"}.fa-crosshairs{--fa:"\f05b"}.fa-person-cane{--fa:"\e53c"}.fa-tent{--fa:"\e57d"}.fa-vest-patches{--fa:"\e086"}.fa-check-double{--fa:"\f560"}.fa-arrow-down-a-z,.fa-sort-alpha-asc,.fa-sort-alpha-down{--fa:"\f15d"}.fa-money-bill-wheat{--fa:"\e52a"}.fa-cookie{--fa:"\f563"}.fa-arrow-left-rotate,.fa-arrow-rotate-back,.fa-arrow-rotate-backward,.fa-arrow-rotate-left,.fa-undo{--fa:"\f0e2"}.fa-hard-drive,.fa-hdd{--fa:"\f0a0"}.fa-face-grin-squint-tears,.fa-grin-squint-tears{--fa:"\f586"}.fa-dumbbell{--fa:"\f44b"}.fa-list-alt,.fa-rectangle-list{--fa:"\f022"}.fa-tarp-droplet{--fa:"\e57c"}.fa-house-medical-circle-check{--fa:"\e511"}.fa-person-skiing-nordic,.fa-skiing-nordic{--fa:"\f7ca"}.fa-calendar-plus{--fa:"\f271"}.fa-plane-arrival{--fa:"\f5af"}.fa-arrow-alt-circle-left,.fa-circle-left{--fa:"\f359"}.fa-subway,.fa-train-subway{--fa:"\f239"}.fa-chart-gantt{--fa:"\e0e4"}.fa-indian-rupee,.fa-indian-rupee-sign,.fa-inr{--fa:"\e1bc"}.fa-crop-alt,.fa-crop-simple{--fa:"\f565"}.fa-money-bill-1,.fa-money-bill-alt{--fa:"\f3d1"}.fa-left-long,.fa-long-arrow-alt-left{--fa:"\f30a"}.fa-dna{--fa:"\f471"}.fa-virus-slash{--fa:"\e075"}.fa-minus,.fa-subtract{--fa:"\f068"}.fa-chess{--fa:"\f439"}.fa-arrow-left-long,.fa-long-arrow-left{--fa:"\f177"}.fa-plug-circle-check{--fa:"\e55c"}.fa-street-view{--fa:"\f21d"}.fa-franc-sign{--fa:"\e18f"}.fa-volume-off{--fa:"\f026"}.fa-american-sign-language-interpreting,.fa-asl-interpreting,.fa-hands-american-sign-language-interpreting,.fa-hands-asl-interpreting{--fa:"\f2a3"}.fa-cog,.fa-gear{--fa:"\f013"}.fa-droplet-slash,.fa-tint-slash{--fa:"\f5c7"}.fa-mosque{--fa:"\f678"}.fa-mosquito{--fa:"\e52b"}.fa-star-of-david{--fa:"\f69a"}.fa-person-military-rifle{--fa:"\e54b"}.fa-cart-shopping,.fa-shopping-cart{--fa:"\f07a"}.fa-vials{--fa:"\f493"}.fa-plug-circle-plus{--fa:"\e55f"}.fa-place-of-worship{--fa:"\f67f"}.fa-grip-vertical{--fa:"\f58e"}.fa-hexagon-nodes{--fa:"\e699"}.fa-arrow-turn-up,.fa-level-up{--fa:"\f148"}.fa-u{--fa:"\55"}.fa-square-root-alt,.fa-square-root-variable{--fa:"\f698"}.fa-clock,.fa-clock-four{--fa:"\f017"}.fa-backward-step,.fa-step-backward{--fa:"\f048"}.fa-pallet{--fa:"\f482"}.fa-faucet{--fa:"\e005"}.fa-baseball-bat-ball{--fa:"\f432"}.fa-s{--fa:"\53"}.fa-timeline{--fa:"\e29c"}.fa-keyboard{--fa:"\f11c"}.fa-caret-down{--fa:"\f0d7"}.fa-clinic-medical,.fa-house-chimney-medical{--fa:"\f7f2"}.fa-temperature-3,.fa-temperature-three-quarters,.fa-thermometer-3,.fa-thermometer-three-quarters{--fa:"\f2c8"}.fa-mobile-android-alt,.fa-mobile-screen{--fa:"\f3cf"}.fa-plane-up{--fa:"\e22d"}.fa-piggy-bank{--fa:"\f4d3"}.fa-battery-3,.fa-battery-half{--fa:"\f242"}.fa-mountain-city{--fa:"\e52e"}.fa-coins{--fa:"\f51e"}.fa-khanda{--fa:"\f66d"}.fa-sliders,.fa-sliders-h{--fa:"\f1de"}.fa-folder-tree{--fa:"\f802"}.fa-network-wired{--fa:"\f6ff"}.fa-map-pin{--fa:"\f276"}.fa-hamsa{--fa:"\f665"}.fa-cent-sign{--fa:"\e3f5"}.fa-flask{--fa:"\f0c3"}.fa-person-pregnant{--fa:"\e31e"}.fa-wand-sparkles{--fa:"\f72b"}.fa-ellipsis-v,.fa-ellipsis-vertical{--fa:"\f142"}.fa-ticket{--fa:"\f145"}.fa-power-off{--fa:"\f011"}.fa-long-arrow-alt-right,.fa-right-long{--fa:"\f30b"}.fa-flag-usa{--fa:"\f74d"}.fa-laptop-file{--fa:"\e51d"}.fa-teletype,.fa-tty{--fa:"\f1e4"}.fa-diagram-next{--fa:"\e476"}.fa-person-rifle{--fa:"\e54e"}.fa-house-medical-circle-exclamation{--fa:"\e512"}.fa-closed-captioning{--fa:"\f20a"}.fa-hiking,.fa-person-hiking{--fa:"\f6ec"}.fa-venus-double{--fa:"\f226"}.fa-images{--fa:"\f302"}.fa-calculator{--fa:"\f1ec"}.fa-people-pulling{--fa:"\e535"}.fa-n{--fa:"\4e"}.fa-cable-car,.fa-tram{--fa:"\f7da"}.fa-cloud-rain{--fa:"\f73d"}.fa-building-circle-xmark{--fa:"\e4d4"}.fa-ship{--fa:"\f21a"}.fa-arrows-down-to-line{--fa:"\e4b8"}.fa-download{--fa:"\f019"}.fa-face-grin,.fa-grin{--fa:"\f580"}.fa-backspace,.fa-delete-left{--fa:"\f55a"}.fa-eye-dropper,.fa-eye-dropper-empty,.fa-eyedropper{--fa:"\f1fb"}.fa-file-circle-check{--fa:"\e5a0"}.fa-forward{--fa:"\f04e"}.fa-mobile,.fa-mobile-android,.fa-mobile-phone{--fa:"\f3ce"}.fa-face-meh,.fa-meh{--fa:"\f11a"}.fa-align-center{--fa:"\f037"}.fa-book-dead,.fa-book-skull{--fa:"\f6b7"}.fa-drivers-license,.fa-id-card{--fa:"\f2c2"}.fa-dedent,.fa-outdent{--fa:"\f03b"}.fa-heart-circle-exclamation{--fa:"\e4fe"}.fa-home,.fa-home-alt,.fa-home-lg-alt,.fa-house{--fa:"\f015"}.fa-calendar-week{--fa:"\f784"}.fa-laptop-medical{--fa:"\f812"}.fa-b{--fa:"\42"}.fa-file-medical{--fa:"\f477"}.fa-dice-one{--fa:"\f525"}.fa-kiwi-bird{--fa:"\f535"}.fa-arrow-right-arrow-left,.fa-exchange{--fa:"\f0ec"}.fa-redo-alt,.fa-rotate-forward,.fa-rotate-right{--fa:"\f2f9"}.fa-cutlery,.fa-utensils{--fa:"\f2e7"}.fa-arrow-up-wide-short,.fa-sort-amount-up{--fa:"\f161"}.fa-mill-sign{--fa:"\e1ed"}.fa-bowl-rice{--fa:"\e2eb"}.fa-skull{--fa:"\f54c"}.fa-broadcast-tower,.fa-tower-broadcast{--fa:"\f519"}.fa-truck-pickup{--fa:"\f63c"}.fa-long-arrow-alt-up,.fa-up-long{--fa:"\f30c"}.fa-stop{--fa:"\f04d"}.fa-code-merge{--fa:"\f387"}.fa-upload{--fa:"\f093"}.fa-hurricane{--fa:"\f751"}.fa-mound{--fa:"\e52d"}.fa-toilet-portable{--fa:"\e583"}.fa-compact-disc{--fa:"\f51f"}.fa-file-arrow-down,.fa-file-download{--fa:"\f56d"}.fa-caravan{--fa:"\f8ff"}.fa-shield-cat{--fa:"\e572"}.fa-bolt,.fa-zap{--fa:"\f0e7"}.fa-glass-water{--fa:"\e4f4"}.fa-oil-well{--fa:"\e532"}.fa-vault{--fa:"\e2c5"}.fa-mars{--fa:"\f222"}.fa-toilet{--fa:"\f7d8"}.fa-plane-circle-xmark{--fa:"\e557"}.fa-cny,.fa-jpy,.fa-rmb,.fa-yen,.fa-yen-sign{--fa:"\f157"}.fa-rouble,.fa-rub,.fa-ruble,.fa-ruble-sign{--fa:"\f158"}.fa-sun{--fa:"\f185"}.fa-guitar{--fa:"\f7a6"}.fa-face-laugh-wink,.fa-laugh-wink{--fa:"\f59c"}.fa-horse-head{--fa:"\f7ab"}.fa-bore-hole{--fa:"\e4c3"}.fa-industry{--fa:"\f275"}.fa-arrow-alt-circle-down,.fa-circle-down{--fa:"\f358"}.fa-arrows-turn-to-dots{--fa:"\e4c1"}.fa-florin-sign{--fa:"\e184"}.fa-arrow-down-short-wide,.fa-sort-amount-desc,.fa-sort-amount-down-alt{--fa:"\f884"}.fa-less-than{--fa:"\3c"}.fa-angle-down{--fa:"\f107"}.fa-car-tunnel{--fa:"\e4de"}.fa-head-side-cough{--fa:"\e061"}.fa-grip-lines{--fa:"\f7a4"}.fa-thumbs-down{--fa:"\f165"}.fa-user-lock{--fa:"\f502"}.fa-arrow-right-long,.fa-long-arrow-right{--fa:"\f178"}.fa-anchor-circle-xmark{--fa:"\e4ac"}.fa-ellipsis,.fa-ellipsis-h{--fa:"\f141"}.fa-chess-pawn{--fa:"\f443"}.fa-first-aid,.fa-kit-medical{--fa:"\f479"}.fa-person-through-window{--fa:"\e5a9"}.fa-toolbox{--fa:"\f552"}.fa-hands-holding-circle{--fa:"\e4fb"}.fa-bug{--fa:"\f188"}.fa-credit-card,.fa-credit-card-alt{--fa:"\f09d"}.fa-automobile,.fa-car{--fa:"\f1b9"}.fa-hand-holding-hand{--fa:"\e4f7"}.fa-book-open-reader,.fa-book-reader{--fa:"\f5da"}.fa-mountain-sun{--fa:"\e52f"}.fa-arrows-left-right-to-line{--fa:"\e4ba"}.fa-dice-d20{--fa:"\f6cf"}.fa-truck-droplet{--fa:"\e58c"}.fa-file-circle-xmark{--fa:"\e5a1"}.fa-temperature-arrow-up,.fa-temperature-up{--fa:"\e040"}.fa-medal{--fa:"\f5a2"}.fa-bed{--fa:"\f236"}.fa-h-square,.fa-square-h{--fa:"\f0fd"}.fa-podcast{--fa:"\f2ce"}.fa-temperature-4,.fa-temperature-full,.fa-thermometer-4,.fa-thermometer-full{--fa:"\f2c7"}.fa-bell{--fa:"\f0f3"}.fa-superscript{--fa:"\f12b"}.fa-plug-circle-xmark{--fa:"\e560"}.fa-star-of-life{--fa:"\f621"}.fa-phone-slash{--fa:"\f3dd"}.fa-paint-roller{--fa:"\f5aa"}.fa-hands-helping,.fa-handshake-angle{--fa:"\f4c4"}.fa-location-dot,.fa-map-marker-alt{--fa:"\f3c5"}.fa-file{--fa:"\f15b"}.fa-greater-than{--fa:"\3e"}.fa-person-swimming,.fa-swimmer{--fa:"\f5c4"}.fa-arrow-down{--fa:"\f063"}.fa-droplet,.fa-tint{--fa:"\f043"}.fa-eraser{--fa:"\f12d"}.fa-earth,.fa-earth-america,.fa-earth-americas,.fa-globe-americas{--fa:"\f57d"}.fa-person-burst{--fa:"\e53b"}.fa-dove{--fa:"\f4ba"}.fa-battery-0,.fa-battery-empty{--fa:"\f244"}.fa-socks{--fa:"\f696"}.fa-inbox{--fa:"\f01c"}.fa-section{--fa:"\e447"}.fa-gauge-high,.fa-tachometer-alt,.fa-tachometer-alt-fast{--fa:"\f625"}.fa-envelope-open-text{--fa:"\f658"}.fa-hospital,.fa-hospital-alt,.fa-hospital-wide{--fa:"\f0f8"}.fa-wine-bottle{--fa:"\f72f"}.fa-chess-rook{--fa:"\f447"}.fa-bars-staggered,.fa-reorder,.fa-stream{--fa:"\f550"}.fa-dharmachakra{--fa:"\f655"}.fa-hotdog{--fa:"\f80f"}.fa-blind,.fa-person-walking-with-cane{--fa:"\f29d"}.fa-drum{--fa:"\f569"}.fa-ice-cream{--fa:"\f810"}.fa-heart-circle-bolt{--fa:"\e4fc"}.fa-fax{--fa:"\f1ac"}.fa-paragraph{--fa:"\f1dd"}.fa-check-to-slot,.fa-vote-yea{--fa:"\f772"}.fa-star-half{--fa:"\f089"}.fa-boxes,.fa-boxes-alt,.fa-boxes-stacked{--fa:"\f468"}.fa-chain,.fa-link{--fa:"\f0c1"}.fa-assistive-listening-systems,.fa-ear-listen{--fa:"\f2a2"}.fa-tree-city{--fa:"\e587"}.fa-play{--fa:"\f04b"}.fa-font{--fa:"\f031"}.fa-table-cells-row-lock{--fa:"\e67a"}.fa-rupiah-sign{--fa:"\e23d"}.fa-magnifying-glass,.fa-search{--fa:"\f002"}.fa-ping-pong-paddle-ball,.fa-table-tennis,.fa-table-tennis-paddle-ball{--fa:"\f45d"}.fa-diagnoses,.fa-person-dots-from-line{--fa:"\f470"}.fa-trash-can-arrow-up,.fa-trash-restore-alt{--fa:"\f82a"}.fa-naira-sign{--fa:"\e1f6"}.fa-cart-arrow-down{--fa:"\f218"}.fa-walkie-talkie{--fa:"\f8ef"}.fa-file-edit,.fa-file-pen{--fa:"\f31c"}.fa-receipt{--fa:"\f543"}.fa-pen-square,.fa-pencil-square,.fa-square-pen{--fa:"\f14b"}.fa-suitcase-rolling{--fa:"\f5c1"}.fa-person-circle-exclamation{--fa:"\e53f"}.fa-chevron-down{--fa:"\f078"}.fa-battery,.fa-battery-5,.fa-battery-full{--fa:"\f240"}.fa-skull-crossbones{--fa:"\f714"}.fa-code-compare{--fa:"\e13a"}.fa-list-dots,.fa-list-ul{--fa:"\f0ca"}.fa-school-lock{--fa:"\e56f"}.fa-tower-cell{--fa:"\e585"}.fa-down-long,.fa-long-arrow-alt-down{--fa:"\f309"}.fa-ranking-star{--fa:"\e561"}.fa-chess-king{--fa:"\f43f"}.fa-person-harassing{--fa:"\e549"}.fa-brazilian-real-sign{--fa:"\e46c"}.fa-landmark-alt,.fa-landmark-dome{--fa:"\f752"}.fa-arrow-up{--fa:"\f062"}.fa-television,.fa-tv,.fa-tv-alt{--fa:"\f26c"}.fa-shrimp{--fa:"\e448"}.fa-list-check,.fa-tasks{--fa:"\f0ae"}.fa-jug-detergent{--fa:"\e519"}.fa-circle-user,.fa-user-circle{--fa:"\f2bd"}.fa-user-shield{--fa:"\f505"}.fa-wind{--fa:"\f72e"}.fa-car-burst,.fa-car-crash{--fa:"\f5e1"}.fa-y{--fa:"\59"}.fa-person-snowboarding,.fa-snowboarding{--fa:"\f7ce"}.fa-shipping-fast,.fa-truck-fast{--fa:"\f48b"}.fa-fish{--fa:"\f578"}.fa-user-graduate{--fa:"\f501"}.fa-adjust,.fa-circle-half-stroke{--fa:"\f042"}.fa-clapperboard{--fa:"\e131"}.fa-circle-radiation,.fa-radiation-alt{--fa:"\f7ba"}.fa-baseball,.fa-baseball-ball{--fa:"\f433"}.fa-jet-fighter-up{--fa:"\e518"}.fa-diagram-project,.fa-project-diagram{--fa:"\f542"}.fa-copy{--fa:"\f0c5"}.fa-volume-mute,.fa-volume-times,.fa-volume-xmark{--fa:"\f6a9"}.fa-hand-sparkles{--fa:"\e05d"}.fa-grip,.fa-grip-horizontal{--fa:"\f58d"}.fa-share-from-square,.fa-share-square{--fa:"\f14d"}.fa-child-combatant,.fa-child-rifle{--fa:"\e4e0"}.fa-gun{--fa:"\e19b"}.fa-phone-square,.fa-square-phone{--fa:"\f098"}.fa-add,.fa-plus{--fa:"\2b"}.fa-expand{--fa:"\f065"}.fa-computer{--fa:"\e4e5"}.fa-close,.fa-multiply,.fa-remove,.fa-times,.fa-xmark{--fa:"\f00d"}.fa-arrows,.fa-arrows-up-down-left-right{--fa:"\f047"}.fa-chalkboard-teacher,.fa-chalkboard-user{--fa:"\f51c"}.fa-peso-sign{--fa:"\e222"}.fa-building-shield{--fa:"\e4d8"}.fa-baby{--fa:"\f77c"}.fa-users-line{--fa:"\e592"}.fa-quote-left,.fa-quote-left-alt{--fa:"\f10d"}.fa-tractor{--fa:"\f722"}.fa-trash-arrow-up,.fa-trash-restore{--fa:"\f829"}.fa-arrow-down-up-lock{--fa:"\e4b0"}.fa-lines-leaning{--fa:"\e51e"}.fa-ruler-combined{--fa:"\f546"}.fa-copyright{--fa:"\f1f9"}.fa-equals{--fa:"\3d"}.fa-blender{--fa:"\f517"}.fa-teeth{--fa:"\f62e"}.fa-ils,.fa-shekel,.fa-shekel-sign,.fa-sheqel,.fa-sheqel-sign{--fa:"\f20b"}.fa-map{--fa:"\f279"}.fa-rocket{--fa:"\f135"}.fa-photo-film,.fa-photo-video{--fa:"\f87c"}.fa-folder-minus{--fa:"\f65d"}.fa-hexagon-nodes-bolt{--fa:"\e69a"}.fa-store{--fa:"\f54e"}.fa-arrow-trend-up{--fa:"\e098"}.fa-plug-circle-minus{--fa:"\e55e"}.fa-sign,.fa-sign-hanging{--fa:"\f4d9"}.fa-bezier-curve{--fa:"\f55b"}.fa-bell-slash{--fa:"\f1f6"}.fa-tablet,.fa-tablet-android{--fa:"\f3fb"}.fa-school-flag{--fa:"\e56e"}.fa-fill{--fa:"\f575"}.fa-angle-up{--fa:"\f106"}.fa-drumstick-bite{--fa:"\f6d7"}.fa-holly-berry{--fa:"\f7aa"}.fa-chevron-left{--fa:"\f053"}.fa-bacteria{--fa:"\e059"}.fa-hand-lizard{--fa:"\f258"}.fa-notdef{--fa:"\e1fe"}.fa-disease{--fa:"\f7fa"}.fa-briefcase-medical{--fa:"\f469"}.fa-genderless{--fa:"\f22d"}.fa-chevron-right{--fa:"\f054"}.fa-retweet{--fa:"\f079"}.fa-car-alt,.fa-car-rear{--fa:"\f5de"}.fa-pump-soap{--fa:"\e06b"}.fa-video-slash{--fa:"\f4e2"}.fa-battery-2,.fa-battery-quarter{--fa:"\f243"}.fa-radio{--fa:"\f8d7"}.fa-baby-carriage,.fa-carriage-baby{--fa:"\f77d"}.fa-traffic-light{--fa:"\f637"}.fa-thermometer{--fa:"\f491"}.fa-vr-cardboard{--fa:"\f729"}.fa-hand-middle-finger{--fa:"\f806"}.fa-percent,.fa-percentage{--fa:"\25"}.fa-truck-moving{--fa:"\f4df"}.fa-glass-water-droplet{--fa:"\e4f5"}.fa-display{--fa:"\e163"}.fa-face-smile,.fa-smile{--fa:"\f118"}.fa-thumb-tack,.fa-thumbtack{--fa:"\f08d"}.fa-trophy{--fa:"\f091"}.fa-person-praying,.fa-pray{--fa:"\f683"}.fa-hammer{--fa:"\f6e3"}.fa-hand-peace{--fa:"\f25b"}.fa-rotate,.fa-sync-alt{--fa:"\f2f1"}.fa-spinner{--fa:"\f110"}.fa-robot{--fa:"\f544"}.fa-peace{--fa:"\f67c"}.fa-cogs,.fa-gears{--fa:"\f085"}.fa-warehouse{--fa:"\f494"}.fa-arrow-up-right-dots{--fa:"\e4b7"}.fa-splotch{--fa:"\f5bc"}.fa-face-grin-hearts,.fa-grin-hearts{--fa:"\f584"}.fa-dice-four{--fa:"\f524"}.fa-sim-card{--fa:"\f7c4"}.fa-transgender,.fa-transgender-alt{--fa:"\f225"}.fa-mercury{--fa:"\f223"}.fa-arrow-turn-down,.fa-level-down{--fa:"\f149"}.fa-person-falling-burst{--fa:"\e547"}.fa-award{--fa:"\f559"}.fa-ticket-alt,.fa-ticket-simple{--fa:"\f3ff"}.fa-building{--fa:"\f1ad"}.fa-angle-double-left,.fa-angles-left{--fa:"\f100"}.fa-qrcode{--fa:"\f029"}.fa-clock-rotate-left,.fa-history{--fa:"\f1da"}.fa-face-grin-beam-sweat,.fa-grin-beam-sweat{--fa:"\f583"}.fa-arrow-right-from-file,.fa-file-export{--fa:"\f56e"}.fa-shield,.fa-shield-blank{--fa:"\f132"}.fa-arrow-up-short-wide,.fa-sort-amount-up-alt{--fa:"\f885"}.fa-comment-nodes{--fa:"\e696"}.fa-house-medical{--fa:"\e3b2"}.fa-golf-ball,.fa-golf-ball-tee{--fa:"\f450"}.fa-chevron-circle-left,.fa-circle-chevron-left{--fa:"\f137"}.fa-house-chimney-window{--fa:"\e00d"}.fa-pen-nib{--fa:"\f5ad"}.fa-tent-arrow-turn-left{--fa:"\e580"}.fa-tents{--fa:"\e582"}.fa-magic,.fa-wand-magic{--fa:"\f0d0"}.fa-dog{--fa:"\f6d3"}.fa-carrot{--fa:"\f787"}.fa-moon{--fa:"\f186"}.fa-wine-glass-alt,.fa-wine-glass-empty{--fa:"\f5ce"}.fa-cheese{--fa:"\f7ef"}.fa-yin-yang{--fa:"\f6ad"}.fa-music{--fa:"\f001"}.fa-code-commit{--fa:"\f386"}.fa-temperature-low{--fa:"\f76b"}.fa-biking,.fa-person-biking{--fa:"\f84a"}.fa-broom{--fa:"\f51a"}.fa-shield-heart{--fa:"\e574"}.fa-gopuram{--fa:"\f664"}.fa-earth-oceania,.fa-globe-oceania{--fa:"\e47b"}.fa-square-xmark,.fa-times-square,.fa-xmark-square{--fa:"\f2d3"}.fa-hashtag{--fa:"\23"}.fa-expand-alt,.fa-up-right-and-down-left-from-center{--fa:"\f424"}.fa-oil-can{--fa:"\f613"}.fa-t{--fa:"\54"}.fa-hippo{--fa:"\f6ed"}.fa-chart-column{--fa:"\e0e3"}.fa-infinity{--fa:"\f534"}.fa-vial-circle-check{--fa:"\e596"}.fa-person-arrow-down-to-line{--fa:"\e538"}.fa-voicemail{--fa:"\f897"}.fa-fan{--fa:"\f863"}.fa-person-walking-luggage{--fa:"\e554"}.fa-arrows-alt-v,.fa-up-down{--fa:"\f338"}.fa-cloud-moon-rain{--fa:"\f73c"}.fa-calendar{--fa:"\f133"}.fa-trailer{--fa:"\e041"}.fa-bahai,.fa-haykal{--fa:"\f666"}.fa-sd-card{--fa:"\f7c2"}.fa-dragon{--fa:"\f6d5"}.fa-shoe-prints{--fa:"\f54b"}.fa-circle-plus,.fa-plus-circle{--fa:"\f055"}.fa-face-grin-tongue-wink,.fa-grin-tongue-wink{--fa:"\f58b"}.fa-hand-holding{--fa:"\f4bd"}.fa-plug-circle-exclamation{--fa:"\e55d"}.fa-chain-broken,.fa-chain-slash,.fa-link-slash,.fa-unlink{--fa:"\f127"}.fa-clone{--fa:"\f24d"}.fa-person-walking-arrow-loop-left{--fa:"\e551"}.fa-arrow-up-z-a,.fa-sort-alpha-up-alt{--fa:"\f882"}.fa-fire-alt,.fa-fire-flame-curved{--fa:"\f7e4"}.fa-tornado{--fa:"\f76f"}.fa-file-circle-plus{--fa:"\e494"}.fa-book-quran,.fa-quran{--fa:"\f687"}.fa-anchor{--fa:"\f13d"}.fa-border-all{--fa:"\f84c"}.fa-angry,.fa-face-angry{--fa:"\f556"}.fa-cookie-bite{--fa:"\f564"}.fa-arrow-trend-down{--fa:"\e097"}.fa-feed,.fa-rss{--fa:"\f09e"}.fa-draw-polygon{--fa:"\f5ee"}.fa-balance-scale,.fa-scale-balanced{--fa:"\f24e"}.fa-gauge-simple-high,.fa-tachometer,.fa-tachometer-fast{--fa:"\f62a"}.fa-shower{--fa:"\f2cc"}.fa-desktop,.fa-desktop-alt{--fa:"\f390"}.fa-m{--fa:"\4d"}.fa-table-list,.fa-th-list{--fa:"\f00b"}.fa-comment-sms,.fa-sms{--fa:"\f7cd"}.fa-book{--fa:"\f02d"}.fa-user-plus{--fa:"\f234"}.fa-check{--fa:"\f00c"}.fa-battery-4,.fa-battery-three-quarters{--fa:"\f241"}.fa-house-circle-check{--fa:"\e509"}.fa-angle-left{--fa:"\f104"}.fa-diagram-successor{--fa:"\e47a"}.fa-truck-arrow-right{--fa:"\e58b"}.fa-arrows-split-up-and-left{--fa:"\e4bc"}.fa-fist-raised,.fa-hand-fist{--fa:"\f6de"}.fa-cloud-moon{--fa:"\f6c3"}.fa-briefcase{--fa:"\f0b1"}.fa-person-falling{--fa:"\e546"}.fa-image-portrait,.fa-portrait{--fa:"\f3e0"}.fa-user-tag{--fa:"\f507"}.fa-rug{--fa:"\e569"}.fa-earth-europe,.fa-globe-europe{--fa:"\f7a2"}.fa-cart-flatbed-suitcase,.fa-luggage-cart{--fa:"\f59d"}.fa-rectangle-times,.fa-rectangle-xmark,.fa-times-rectangle,.fa-window-close{--fa:"\f410"}.fa-baht-sign{--fa:"\e0ac"}.fa-book-open{--fa:"\f518"}.fa-book-journal-whills,.fa-journal-whills{--fa:"\f66a"}.fa-handcuffs{--fa:"\e4f8"}.fa-exclamation-triangle,.fa-triangle-exclamation,.fa-warning{--fa:"\f071"}.fa-database{--fa:"\f1c0"}.fa-mail-forward,.fa-share{--fa:"\f064"}.fa-bottle-droplet{--fa:"\e4c4"}.fa-mask-face{--fa:"\e1d7"}.fa-hill-rockslide{--fa:"\e508"}.fa-exchange-alt,.fa-right-left{--fa:"\f362"}.fa-paper-plane{--fa:"\f1d8"}.fa-road-circle-exclamation{--fa:"\e565"}.fa-dungeon{--fa:"\f6d9"}.fa-align-right{--fa:"\f038"}.fa-money-bill-1-wave,.fa-money-bill-wave-alt{--fa:"\f53b"}.fa-life-ring{--fa:"\f1cd"}.fa-hands,.fa-sign-language,.fa-signing{--fa:"\f2a7"}.fa-calendar-day{--fa:"\f783"}.fa-ladder-water,.fa-swimming-pool,.fa-water-ladder{--fa:"\f5c5"}.fa-arrows-up-down,.fa-arrows-v{--fa:"\f07d"}.fa-face-grimace,.fa-grimace{--fa:"\f57f"}.fa-wheelchair-alt,.fa-wheelchair-move{--fa:"\e2ce"}.fa-level-down-alt,.fa-turn-down{--fa:"\f3be"}.fa-person-walking-arrow-right{--fa:"\e552"}.fa-envelope-square,.fa-square-envelope{--fa:"\f199"}.fa-dice{--fa:"\f522"}.fa-bowling-ball{--fa:"\f436"}.fa-brain{--fa:"\f5dc"}.fa-band-aid,.fa-bandage{--fa:"\f462"}.fa-calendar-minus{--fa:"\f272"}.fa-circle-xmark,.fa-times-circle,.fa-xmark-circle{--fa:"\f057"}.fa-gifts{--fa:"\f79c"}.fa-hotel{--fa:"\f594"}.fa-earth-asia,.fa-globe-asia{--fa:"\f57e"}.fa-id-card-alt,.fa-id-card-clip{--fa:"\f47f"}.fa-magnifying-glass-plus,.fa-search-plus{--fa:"\f00e"}.fa-thumbs-up{--fa:"\f164"}.fa-user-clock{--fa:"\f4fd"}.fa-allergies,.fa-hand-dots{--fa:"\f461"}.fa-file-invoice{--fa:"\f570"}.fa-window-minimize{--fa:"\f2d1"}.fa-coffee,.fa-mug-saucer{--fa:"\f0f4"}.fa-brush{--fa:"\f55d"}.fa-file-half-dashed{--fa:"\e698"}.fa-mask{--fa:"\f6fa"}.fa-magnifying-glass-minus,.fa-search-minus{--fa:"\f010"}.fa-ruler-vertical{--fa:"\f548"}.fa-user-alt,.fa-user-large{--fa:"\f406"}.fa-train-tram{--fa:"\e5b4"}.fa-user-nurse{--fa:"\f82f"}.fa-syringe{--fa:"\f48e"}.fa-cloud-sun{--fa:"\f6c4"}.fa-stopwatch-20{--fa:"\e06f"}.fa-square-full{--fa:"\f45c"}.fa-magnet{--fa:"\f076"}.fa-jar{--fa:"\e516"}.fa-note-sticky,.fa-sticky-note{--fa:"\f249"}.fa-bug-slash{--fa:"\e490"}.fa-arrow-up-from-water-pump{--fa:"\e4b6"}.fa-bone{--fa:"\f5d7"}.fa-table-cells-row-unlock{--fa:"\e691"}.fa-user-injured{--fa:"\f728"}.fa-face-sad-tear,.fa-sad-tear{--fa:"\f5b4"}.fa-plane{--fa:"\f072"}.fa-tent-arrows-down{--fa:"\e581"}.fa-exclamation{--fa:"\21"}.fa-arrows-spin{--fa:"\e4bb"}.fa-print{--fa:"\f02f"}.fa-try,.fa-turkish-lira,.fa-turkish-lira-sign{--fa:"\e2bb"}.fa-dollar,.fa-dollar-sign,.fa-usd{--fa:"\24"}.fa-x{--fa:"\58"}.fa-magnifying-glass-dollar,.fa-search-dollar{--fa:"\f688"}.fa-users-cog,.fa-users-gear{--fa:"\f509"}.fa-person-military-pointing{--fa:"\e54a"}.fa-bank,.fa-building-columns,.fa-institution,.fa-museum,.fa-university{--fa:"\f19c"}.fa-umbrella{--fa:"\f0e9"}.fa-trowel{--fa:"\e589"}.fa-d{--fa:"\44"}.fa-stapler{--fa:"\e5af"}.fa-masks-theater,.fa-theater-masks{--fa:"\f630"}.fa-kip-sign{--fa:"\e1c4"}.fa-hand-point-left{--fa:"\f0a5"}.fa-handshake-alt,.fa-handshake-simple{--fa:"\f4c6"}.fa-fighter-jet,.fa-jet-fighter{--fa:"\f0fb"}.fa-share-alt-square,.fa-square-share-nodes{--fa:"\f1e1"}.fa-barcode{--fa:"\f02a"}.fa-plus-minus{--fa:"\e43c"}.fa-video,.fa-video-camera{--fa:"\f03d"}.fa-graduation-cap,.fa-mortar-board{--fa:"\f19d"}.fa-hand-holding-medical{--fa:"\e05c"}.fa-person-circle-check{--fa:"\e53e"}.fa-level-up-alt,.fa-turn-up{--fa:"\f3bf"} +.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0} \ No newline at end of file diff --git a/src/WebExpress.WebUI/Assets/css/solid.css b/src/WebExpress.WebUI/Assets/css/solid.css index ab3588bc..dc22a275 100644 --- a/src/WebExpress.WebUI/Assets/css/solid.css +++ b/src/WebExpress.WebUI/Assets/css/solid.css @@ -1,16 +1,22 @@ /*! - * Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com + * Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2024 Fonticons, Inc. */ +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; +} + @font-face { - font-family: 'Font Awesome 5 Free'; - font-style: normal; - font-weight: 900; - font-display: block; - src: url("../fonts/fa-solid-900.eot"); - src: url("../fonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../fonts/fa-solid-900.woff2") format("woff2"), url("../fonts/fa-solid-900.woff") format("woff"), url("../fonts/fa-solid-900.ttf") format("truetype"), url("../fonts/fa-solid-900.svg#fontawesome") format("svg"); } + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); +} -.fa, -.fas { - font-family: 'Font Awesome 5 Free'; - font-weight: 900; } +.fas, +.fa-solid { + font-weight: 900; +} diff --git a/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.eot b/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.eot deleted file mode 100644 index 958684e26ab53aabf8ccce6120963d900dc64fdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136822 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 Te|hlx>irL&{PU}Z@7MfacbId~ diff --git a/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.svg b/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.svg deleted file mode 100644 index 2b7cf17b..00000000 --- a/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.svg +++ /dev/null @@ -1,3717 +0,0 @@ - - - - -Created by FontForge 20200314 at Mon Oct 5 09:50:45 2020 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.ttf b/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.ttf index f071825144b8bb9b0ebdb53121ebe9d96e69fd28..0f82a8360517d2c8b7d16e85434d40c6fb735954 100644 GIT binary patch literal 210792 zcmd4437DKkwfJ52_P%#d?>$>j_ssN6W+s`Qt&@;t2#F*RAj-ZdK}3-?YLLhx!zSp} zOHdY3#Hh&iDk>r>D(YNCL`CI#@# z-rDQbsZ*y;oqD6RQYxq>luH$lJAT>FnLA!}sZzR!(5+`*c-FQrw;XjC3H(YW-~74@ z-tyYDH*9`hscyG&_NC4}=d9QCeY$WDY3~Kb&LzNog8NAP&j6k0UbuaS_XvN0@@`bh zKXJjuXP@PKwdFpgS|@nF?!vQnY;!ibUrs#btKvmxU3kuCKKJZZ%GI1x%H6u{;x}#o z$nVQrl&gKYQn{sywz_;C^@Gb!*>PrU)jkz+$fnevypyM;$D=0Toq0I5-#!Mi`;SQ zlyC#{bB=AtyeWTT{x8%Oc5Hsfzw!FJ)Z0wi zj;U+Xv_rzAY%k!Kbk5aEoB9bSZlSM@JSL6JBlr)>`%8h8Ys%h3yg)r2n3;AG=QioaP1ynBZ1}c%U8YW3hl!&e(l<5A zYoy1G>EG1bK)uxCC(N{W!5vpV^0h6h?_i @@Z|Lo2o%N8V+8O&i2d+$8BHR07ve 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

                                                                                                                                                                                                                                                                                            5|^5S+y3;K7O)x}-z+fXHi%Te^H-7a~a{D;XcI>FxC!rTc&B{`-%1r?#&B=+w2%;nf?|FKRJk&(ZEmDcLCbH>_@( zjk}wU9KE0QioLa`e)DwdhSftN`>X*2z4I%`^noDn;4roxSRCkSeY=Oj{@Rx9>9jrF&)DtxAsHEhFunWzXxPYRywXI{o!u0+HY26C zZMGttW}~TzQqs>Fk!(a(C{H9~olQ|wR@lDTjBe_L;)M;iDIpJTPVm}dU%Z~H=iFy;|bS4Yhky>JYIvpHoIU+}@yfSd^ zoEkXy2X6i0ZMXg5($zb6TyxD1hCacR{VsavFQH{m3R}2G;h26#5h&## zG>+)+#307BakS6l<3ojm1R~iWu#uc=_p+BiZ-1dQHZ~G%c5|a^+q~gifxPQ52_@7I ztSA6(-tz2^eh}8aIAd>8Z}dh=-z|-J^UdGRjpP<)Z`{12HJr&1Z>ne=b26tQ#a&xw zKK#Vm4`QbBCzGjkkVE|fSeF-=I?hwQd*IQ5XUK>DGOFV6aEX2O^E;fiq8LhWd|JB%?paKwm~D5W5bA z$7)e$KDbMgQrzXP1o9I%g0u+kQU4CUep;N~96NA|1;-$7PyRU?CnCC~9i$upobA38 zPN2gOh=n&hd1*m0dL|sF>V&F}lW<(SP^lN<@oIXg(v8_pYKY3BX!VxL8W}S**Bgn#ErajciOxXDDn8}t3|XEOKcD5z z)V{>jN^R#!tK6(RNjZLqQ=k+=sM?BlMkeYbhpckO59t%?OcLH5_!XY4?)Op?oMnu} zVEL1rGar0xG351XiE?Ikeh4~m&a_@_kxEK|1c^rvZ-?amjV0fYL+bgCe66&#+d#Ty zwQ%8koR?E2fsp21wH$JXtI`vy!QzXjzFD3u-ncuTpIx3jT1v))zeMrUr$<+Yo?wtn zdx$4#^RM|xnqsw_X9NdIM2JYz=cW0ahk%Jfga<=RK*>JJP+_HCdgk-LZ23 zU?w_2mFrr4rn9=L3XKK{@k8q)`JZo}SK;tjuHmzF zZ2C9G8)1{1Jt-kqRQj7Wb&}9@eF&JN(f~OxX=7KFp*v#7BY&yN+cQ$R` z_{j3kP2>J{>eI*JM%^~Geb2Vxa#3mZ;>ysLpl#T+jpy-E6u^>kcSU}*t#wUZ)UIq0 zaS%I9+GxK`^kYZTByb;_iQ&Pe=7u+3a_^=4-?YasKs0aOnVer(=yVo5Dm5iDF63#& zvD(Ncr&#xw6T{bTx$KVHkDl2uM9QDJp}BJ4(n}BQztnV7z~XbhgtoAnXtf|3&Vkk_ zfb%&v0HD$ny*W??rL__OlvXJVJVHLbEbf(0&XP|@*}YdY2}4jC=!cO zo*4BBSSrMidIEwh!%hxDGz-ETfWA_>S`>a3{R`EyHb*5y5}LNDEeUq)sw-D6ziu-- zFpZ%tSIz8c7KD>)?U$7Lh(^WY%JOiVn$2^NxG0PIX~N~C>B&OQ1PYiTuIM(JizR=w zQlu)4?u}HdBnN!Dxo76;%|qC-PIU8im#t$Xb9GpHh{C3(Yekl9eL<= zdv1ob7YXLe4FMTLt6+z{X-3;Fb-+bfBXVd&jhG1#r%eEgU83t{)dZYxp%8VQ!c@IL z#g+dGpE7l6A{;N&1cil7g}Bh1ks4_ggoi>82RC}Z%G0eqGpZY5R!{{)EBTQORev?o zDP7+PB~3j>+@D$jMwXN>NCm6}2BDFkHQ`(eM-#q_>DDGIB|@eGgc(w=7axq&W1aH7 zD`JzW)NuQ+IZ4L}Q{NTpafw%Pda#kpl<7r>(&Y+~O3jAC$<|ZRo=N4PEdc%T+2~uA;nC^1ux_QDrY>NMDF25~k&JJet25$=H!J z7q5~|c+efJnL^E@L5!A6r9!dLd^CL9=wOqYG_(g5j8o^3MewR%KSCF{9Kt+=X{0@G z5RIA)5kVoYM5r@FC7HC}ApM}#2mfPAs&irMGv79o!Zk%*bWWF4516S!2|PYGgisLZ za=<>r))TgVTbVr@GvoTT8+Th)A#j4xMQ!t?JGl$O zOd@Q2`B3yBBMtE1wXp%Mk7KDz%8?sNS(ijt%}faM1hM|MwxPLZ&Ka_$%@YHDbu5-T zrFHzT+o)D~`A?3^wy^7<5MVdRH|cwXywLk#_D`B`m|0vT~x?yJ;SV zx{RzMC`&Ig?7n^ZxpU_>j(F!TyX@Gp*l04GLX4|xh9VIsJbEq^J~boW0rLo?2U@Wf zGe=#nTZ6CSCG~&R=kOUx{sJc_G>>$)i(YjM1L1*`(frkya6U+vyYMv))d*0wi!g3! zdtO3j!CfPYLX;i1$?%(*1>47J z>Z-zco>15tG-~ZHk7gM-5Fj4aesHnnrqbLMfO1JA;lxsmLqiYP@THi|gCm(Hd=sXu z=~3)6Sdko55PZ+(#|!=4DXqP*_H(NTGq_brWNSrCGdeW_9fr(u2M9{yY~conqnSu3 zo!$M~n&H=0q*(n0dTUCu1fcsA!wX3anvJm@MyqwnjsVYg)eFZ~EaS|M#>tb7V=Ja{ z<&NoJnKKS-Y;Pae^aC50PO4{*Eg#)^onuBL=CMu3n6mu8SUPTK_08>##|#~qNuR^^ zg}@FJcI7n3mFiIg1LwyVQH{j_Yx;J(qJ;UdpA5mQM4_~S_xtwC%*5Hov_FH?vPex^>_q{T3>QPzo<>s;Gq0`r1dvlnY$q$sbLj~Lu zc^Jiq{JfS@-yo6{A(5P85R5F-J(~x0u$f9YG zS1B>l07q9=Ccg{5HTaMS7oHTcV14{8Sd21yN`M6$ z61m%w&;HN~L$b6!F?Bf?0d_D*3cd=CN10>f1%=37)=%XsBW;9#HW~^=BaXe|lkkTX z`ea-Wr{c&CH4{$}(V!Zh`5llYNFY3px0(!-$ZS3}$Ooy4p{0*RYb#ix}e>BcmO_Fl4}ssz0DL$x!pVkyPA>q(b(u zU{On=Kq#~~M8*X5bt1n)cD)sxJfp`VieorzY;<%t!ARo1sdh;w1u=1sF5#9k1#@;K z+t_2x4poy|=EIw>3`2=@wOgXop(#Y8rb-w$YrtD0=1x7rx>}`P z)woE`u& z`g%5F&rjr1C9w)%Pe)Q^i4k_yVI+xN&bq_NLK`#Ch=roA2TP>V8~HqbV7ImL0{ii% zkhS)4iA||fR)~yR{c%GlQ&o*4EMn2n?;=wvmq~J+=DK>~Z5Nr6cgi-hJnZQGi}sH2(Alrin-FRi}YP)1B0m_A*Fye#>~ z%lr$jRw=3QNMaPar|e9nU1~Qb_l|YqRomU3@ZKIZBO7jtc@re)WMY2oN997hv~x?h zRvS)exv3XE?71oLe)#H^C))nT*+!vV4IRx-x^5-5DHb^xsz$e2D*bknd)PR$b}k9e zaH_qfH9y+UElif>d6CQUH`-(BU06Xg0h>0a&5VRgvOFe>6GidqRIvY~vr-lan~cFB zkd%mqzQp8;8vF~ce7Z|FrMML~E_s_bTEydK0U`P;a~! z6@vrZr>ikYhFRof{@gP#$1qWdDDDk_)rP9qQKbwLUsZTdHUyg!1ED2jAu?EM#R)Uz z0|Rfx6UT^naimEuQcOF>H7<%z{(Jb&@t?z1YY>W&x)6*Eh$VBbMZ~>MyC#l^G=iXQ z7Afw5pn&dGbV^bqB~~L?XjoAqc4v3!WQ0-EE=Q|3VEkiGv zxo=aXk`mZvp0XhTdR!y#Sk;kNRx}A&v zPf_s2EZ~eyb&}p;d%H-YP9~k%+1jKhS=r<<6Es@#6LGIIThM%O_XMX$5XHjV$FL(- zNWPA~_sWlXhFld^UJiSZ`?#!8oUrdT6-<0j9?f_5T{fQMt!irZ!9AO9Y0V$ayF9>vboUtU@v-EYO*m-+XAdzjsh2j2ro&H2Q zJFqn3FTkV&pM)?9GH&E?_E3>91!)n%`2ND4xw$=aA3!3H=*EW<#Y7{w_8YlIBllBE zM|t!Rz!Z5sVu1&wkcSP0plv0rtvBx3bK@T6u<6_$p8t@hZ!@(2#peBu)t+4AGHfR9 zFGT*)=!8jApdbQla#DWQTx07!pa{@=66k`Tr~P-NPNEmIdz;29fU>}AsL#XPZpd)k zkB)OGG*cP5b!F}MI58EGI133FzsP}8(#DdY-~F%+&%Q{SQw(FB^jy1A;8)i2R=;SKNue7fi) zrM3mU67hsvTvE}vjt2n~-_CqE6n{6XR2OrVaIs~TK&_TjtPK0QPA_X0B4*X~D`RHK zOlb8&Q;sc~Iu0pkBxZmC{G&KUld(pUci@I2URX$3wC3z{TNeIpn8&x3l3RP3}? zFy3&Nc8_-8@VR@nds9O#RjO;MTFk+r2urg`s6;OojX^D?74@{9xm&yaDDCNNatuY)W_#<#loM?Y?@MYPW5xA1Xe(Q_k*JH8QX~YzN3W7a8r8-o zwM!?oiLs$rTWhwpDydx|=r{DyVYb+h1cW9>r))5xZ@eKn$Z{}4i6zEkNd?%9D%b0I zQ+Xsn4}|z7j1IIH8PFO3upxm~!ld0-e#Ng74EZp0<0ryuMjaO27G1WNeKkSwHTPy$ z4LC+JW}3%V;&J;+5(Ajqnx-^;(%9*llKCFbeQ916mq3TIG&zeCC=y-wpS|=`Cr&;j zZ?!97n@%G1{y~?Z$6Z4NS4{i=s|U;S_880R!J^91nBR0V&j;I|?Qi>2$N}R5UqOzH znO#3Q26`lZC>hUsT|}B>Zd!BOY; zJidICt4kOR4GB22(_1XKNn$V2O~i$t}Lu=9`@f zqmG}i14oe$1EAxCgL)rGq1y(YB!}}eVEWKw`Vc7_ zSbre50TfF;DV{ExDRGp*BaI>?Wbr|KO>{lcUGbMRf>2lAT}=?t{&#=JNJgyRm*ak<6)zXV>lFx_^EU| zY=@`;aI%Hv631;olgY&y0@?>dQb7V0cSB3r{1SHgB?08N|BEE4h34I8t(w~_y&Fjv zZa{ds4|~Z{S8xC)os2bbISdO2drx+N)Yf9tA6sX)ifV@{Jh{nP)Qi<|55u z7fO(ww`8J`6p_&VKd~_GTG4DH0-6RMl@M@-kVXtJ8tLG@!xl0o8Tg=Q(qLf$ak8Cf zCvl~})3&Jh!pPSPJa%C6EE~Y2)y6L7&LKww`I+@SUz#X7nLzx}vT(k4k<+N5nw1$` zy?!!Zs=d`8s%5XM?@*&l*F%|D9*fR??fqV2b;F%E-+AQN$v?ibyRW7GzF6FUeQl`r zwruLQUE$Dt6CJWM*c%z$R1IhHwaLR-RsQpM;?lP!la<)`>|`v|?$s9G9*W-obIO`W zb_~4oPqew8W=govNBi|k&E~v`XPL93By<2hF{R1bJb1217G)VP=v}6EZtaD&7u4p5 zy1%#`b-8r;d}HgpxAu39jT;-2^|{J>VwsW0_U(IYWJb+A^AYv#A9r7TvHRk=U6}<# z8=dt>24`kwO4GMTvMZ~rD`mBPOPUlA(U<-ieaQ@T-s!$orZd!&0v{A6@_JJWXrL7H z6#A<;-P^K-R<+me_I&m2Qr%oMXG&`?o}aMJ2tLoYv{=fd8sb^U+mXpcHzejpQrTqw zF7@n4Y3;X!-%ZVxM%F$NdXsI2@d;B!(Tt^xH<+bsOIf#)nBL@WjwAr7Sg-u+E3aUO zyoG1I5v2b|$+7+py_DV}h&9S2Az`cr#anQ%(>eY5E~7KOQSdz6zJ8pBA)00|kLv(b zRMxl9y72bRQPidzgd)y=Z6G^@h65`taXzbU2Aa>DDD&(Lbc{fVT09`+ndJ9~af2p+ zPEy7T#vKwRN#p=$lBI$S$INm%flk3b*mJA*YiO*l#;6*x{Fd@YG;Mq^Q_%C-OrHBd zusEX|#cWC)&E|A1?Zq**lV1w!vkb0&SR1No6jae_O)cUvxT!ff-kD|Tz$>*J42$7L z*3oTEbSqRtJDyeTN+{zSgaat6Zs0a78)u@MJut9=<_6c_jw;&{!7CcfTc1M@11 zw=FSlvIDXta&&Q7Gb96qMk|-R*{ph2Z2q-#@~JitZ%%Hu)aK2~T}(0)%T02(GX7*P zrk;IuE!JIor7=3(zU03*+QYkX?V1S^L*pzL8!qmQ?}HPgTY(3H${pO zWPdRdwVFT`EkdP__b3ycTQLYgh`9Ebd}k zd(#HnimzQ)`sFLbG`=J6FX%~vv=rAUJadq`py4ZiVMgd=cgx4OiFt*0O^=ODGgMH4 zbf%U}RA)ur+Pqz^`7RyeG|3G(~ZB1=F@n^p^$SlB6v21R;@qOt6A2 z-=D0vc4fAg@(-2rwdT&$Q;#6OP)S`lRg@@I%<;NcD-2ex9O; zSOqcC(=l%B#H6)hS1enVxT=v&_%;PE#ZT71N3Ea+CNX5WF1ZnMPxz+ULZrj!ZxqzB$AKCY(=1)hPc{jTh zm=-CI(0s%$pLGVwB&DDOxAePKK7^wMl3nVKDKuoVT-M`;=X3Qu*awR1@rjE$kq5{F zhMApG9IyK}UpIgL_kU~oxpVj4@qt%A)}DKHGFW)=yn6Or=#D$?ef4Ab)u~|Fg|jqg z#tHSxe^CFdzDzIl87T&a#6TlXp-*c4XC%2C7S@a|Mhl^xz1GNljrYQ?yB3_#B@0v6 zpV*BI{Lt=DdH#~6!Leka^YnM;Yvw3xt^JO1;GvzHuPbJaq2(*)Zhilk>f2@~i{X*y z?~X2AU{lGxlUfL1NyTnNwqZ5mM+~4?zL*$vFss|L&RdA*y+bHsjF@}1aLA|pn_DOj zwR=iI*V?`;oldU?k)Mw|diwOEr&UXbdF412z>|I`40?ZI)QNO2t-pcw{v-$y{VQvo zew2G6y7Y@`A334nfvUtuMTNnNoz1odbi=s?Cxp$zX<@~xz1g;3pPk(?bEG~wy=!K+ z-WZv0G$tkn*EvUiX99E?W!C3M8ueL7NH~W0RbSEGKppxKys9^VaeT|bJCP;p!kSW5 zl3KYeBQd~B5g9xOqCT7o0|7b{0z#Hfk^XOEYNE}Pm5U-OmSspdN|5$FtgpWCm%&`d z0x2#nYrSVNRZK2ILtq#1LPfJ~sI@%2{eKJ#rT8$k;}3?z z)S(JL>|`lL<=kN#1qMDNAAP574s+0i>6jTH|Ksx{$i&Ag$rCeUi%mQ|%j3;K%Ni-Q z>gn`kq_KI*aOOhW{DNl1Iwj0Ec8{T}vXqnP48`5@&vUrom{xc=JV@YpFq{t#c_hbS zOg?xF=+gf@@Kf4bl#Bf_i%aCG zhjq%UPcfkz-n_0yvf@xTYc}Mce-ZIL7gUxLI}>?0LW*w_av4J_4Cm7sKLR1hTq>6G zT;ON0)ko}D-PEs%dyj=0sY;>-5M|hjZ|3XjJ(-9f8^$+J8S#`0Ufs0HbQbB8FT-#B zEK&m>cCx11ZJ38UKm=#}I9`-Sg-8;WB+oTI{9%>-TkFmC9mXe(?z}!@U30a2J66`( z8|UWK#wmRY{Wk8l_LNG`%mz4@7u9F!>jipxmPk|3)y2lN>`57YaNE!i)$#0>#+iA^ z@t!}^*phX-rP1Z(QLj~g>QJLKhQ>M8Y8>(_%SV=j@hDGVS;w_d>8S2s*5(!FT!TBw7+HVCq0l%SXskCs0&CZDt)tl`> z9n6muAjR&?&JZRRG%-nPz1f*gph{!|9fAW9t>;IM0B#vF;^{u9qbGJhzsL#MU9OjL zR>of-(pgSZ25snxvs56Hty}GB83F1n61@h+g-j9IB?chppY<^m*T?f|)K&Zn>@6z@ z8Aw$W_9t`n7Pja%dHb@7*o?k#ETIB%3wUwZ;3a$JB}<46_7|cVWiu>5k&wH^8_s5m zmRabB-H!N|ddNn(7(N0AM;8g$#g||q94&Z@wSGz>{(JF5bBevzA+&nksT(9QW-<#g z8ypIz+92sT(1M2}l?eDLy&7?$r2kzYrr;~Agx1U#i3E|uT^}hFaHFb0SSX19j-VL{ zw8VmD7I}nfkHG=(iD)&M$o?N{YJB%tqnx7G2@K1QrXy~AMCv~kn_=bqRSED^r2v{{ z{Z2JvlP_KazF0I>vQVD3DZqph$8k~|M9O%_%@~IOhX`$L$nZ#@le305Bcewf$IGF= zxp=h0_@PnO`~>j=%Z;wR&7xvF^}v%>-D0110*93VtMp{3;1MK)FP0=HB7^8#DeUAF zVVQ5@j;2LC1cSb z9?zCczv&p+I;mTJv~(1|!Or?tMU*(vS+S9ln$38t*Kd1cU%a<+A)F&REKiW`BY9J z8vRYBUy}gf6L8f)x3DCijxD`Amqx>j))7NNN2c_98em`(jO3f5x@aS*g1^^MTxOU33Q+KbKq6Y zjGu}b*b2}At0dIQY0sn`eK`{;WJpk^GH_ShWD>PlG6$P=+D!`gGxFBXq!aWiRAdPN zQ0W;c0St}mF&xeeVR%VxMp94(Sh=`CLmOfWbk2*?AQC(*B7?g_c_m#5A_OZjToI)r zOu_P|LdL$G;JQy@cVUf^trF8*ki0nAqhbi`aF$+JDIBR6tqjFu`y#{v^iiEIdhTMV zlzPqbvOAmf@`2~hB{wn^kmhu^e0X^|G3O?{c;K^kgDx0^-zj0+w;gNk~Ew|3e zqgwfn59LR+QwX}W5=-rLvtAx@ZNJ58kJ;iSuJ&+=9n?r+9uWJPwak z4oN*I2ro2Ag-AZki~)jX-6W7K!fZ(xO>DX)gKMPi2Woy!?-M1XX*V$jtfpaT2>2eP zgk52Yu!BLz`u$o!+(0}97Xowr3MabUj6LcjZQ%&k1Ig> zu9v#1GblK(->~!J8y)6vjJ~n-sH6)UO*EGZ{+9+d{leyp)|QTz)3Mp=@W!>%gXZM#B%o#=?9cmrP=JP3+v| zZhh0Q)qHiruU$quGxYwDxrqR4|I_V~eLX-%9 z{82tl#SMU9BSo=g{$pGHr5(LmPMyrvYFpnMr;7zZ9@4XT#|14LfzG)UDPA#-eH(KO zx_}ba$=a}c`;I3yS=;u?v)C&Re$`lZlN2FW<^B9OBx4OuYT6aD2o-bY$T{SRlr< z1N;%JRsE&@Hk-hOZZ}Z>_<}+sfPvC)NGEg5R7{whbkGsGApf$pI<>jE`Q+wF{?)aK zNMY~fM;^L&r4(4|<7Gc-U>CN{?DSTg^-pfbH~;JETXyYw%j)W-Yy8}bYM4`J?%Zsg z?8fptbI@9k>xQ=){;<`fX#wL~ zOc(IF{&0L7ElAo3+kjwq7efQqy62wUdiuIcb&Kj0-RRZqEP5wyH}a(>0FcI|rOAmr z^-f^m(#^xyH|MwhERmrBV)ucQofM_4tsbIgVX%07n?#>=L zSMl{QVVDCLG&#wl^R6?*66*AOSXjIrVBv_h11{d~{4m>rwte;|?TJdUu=j(x#h~2S zct@l>SM($GL;Le{t$1tSWp;OVBDx5jTfVC1d)6m^fY=~(kH1k{a>r-VhiaMWww?OR zWW5?4F1XQ0?8>+|v5cDXVQWh4Y|h=9tG9dDC_i%%iNV%Cg|0ZKx{WV?im{l(njeMF z#N~pgMskV5!1U4k_pjI2Zrb_Lk6v@rt;g=#P){A$ef`wYjn2l+yEjgg}V`u;;J2*={2DQq0cm^uM0Rex{X-GUc(`WL2OBUPg|mDT4a}G z!MBeV+PdO25{Bhq*rQe3YmahB68Dl}ERA0!#!LEyFs67Nn6DzM0SY4laYA;ee4JcA zsfUysv%Wz2V}h>qc085-3=KGuiROPuI8Gv}j>P)ji?oQ_*r3^h7J(1Y1sVxLL@cDJ zHamN%0!olbsu-EX|Z*6(t~v z^`V=CspbUjFbKlsz~RGEPgMi~?ybL8iCiVwB{Yz*FQFH-v1DOhg04Y+Y7~ECu)Nut z@LQmmqnA=uqn>oAl?gu$Z%>Z{qHv(SHMF~Uoa3?<$q=!03igg2ahsQWl}b zQak`yj5(k?E$V*k7+m>|4Xgn>58J44W2Kxd=I8(twNo)@m`XtFNx`_bHW7_@xXSSe zNdSs14UI6B~&7L1@TtLES48EPon#LCt?+mtA*wx z>nG=I2Va$F{g{C+{Cni=Phf2&;IjccNVOCd5@{2+lB8yPVM)qq8F;A2#&Umf?VcmI zs{O55_4E3Ya;`d7FP`3W?IruvOLg_eD_-)tE7jYhbM5i@=+<4$`QDvMz394BS9VgtfKnO0lyO)3)C?s9mlsrf}=>`C_KpPrJ;Z=RFV%@JHuSkGEl9!n1oqH3~zdB@fLW~0|00(2-cmYK7ozilx9t7 z3na7k1@gyM2pNUOBYXxY3W-W*%3Rl}t3!)Zv0~?P%R-8&==CCZlot z2T^|E<-dNO6V#YQL2S||Q%m_`p|CV<(1s=nMmA?uF8t$*Lo=Jhk*0x(z;cTb=lPXv zeqKUrvLiT9%yKch3K*`p@t>M6v59LJLR&c(}8eg`^=d47XDk0s#?QQCdG! ze$-3eQ|%`KGrQ09$_wyxyxKBLule|EcAi;Xo~H&W>ZT7TBkFXrU%e+8bzALrb>V8? zd#4j!*m2!!Uwhr^nVkhfWaWHgIT=AlM&Ne86j^*Xk@QFS9`dnvA4ghTL5X^Xfcb!V ziB}c|6j(Gea-gDNlR2GPL40#5Y#-$6As?&lhm5LSPDKz);UQVZ_OggL);3mbd7GM0 z;#td`k@ zTi=m*m1f+L*mq`S-~Dwf=9rb+*Z04;aDxs%g6EXrQ-~z1uh+EKSCb$@>Y;os>s3n_x5Hnjy?jE6;s-4ftUa~1hHh)lG>LoyO!E_`;F&bcf<92c6aVQa%8yNQSGJt@lFMp>_#@wyXwjhyzl*6UsZ!+Tff`5 z@@I~{UX`}~EO=Rpm^Mu%{!r%CpVO$|fOppS|cGql20fVKNP03S{PzBYt{~Id5 z^-D@^ozJPyxXNAIvuEq~zOnYzZ@%}J&X1iRqw~+N=f6gxt+}zW^~G$?SrL*|0` z76!V&J;LFGaK>I4$_N^E0#2WShinECLAHl&2!zR_*o#CSS-~(9hzpBCNXcMnh?mQ| zZH$QwNg^~v12Aa#kWip54;BV}$-IQt3NjekOF*nULh=T5%w&cF9tdWTiY`tQ(pC@_oS-a?|7u8EMRx0hlIP9PY;>CQTsTvn*Lh2(;ms8?6?v z7JG+41{k0$q~uNEaAn=9^rX_y9vm8NtzeX2{&M9wJe#=;rY;Cb`hJAJUjl4 zs7yKT_O;(7;ib8@oiQzZZbsdtHnR_9K~er>hA6sq zfEJbR8vaqto_v#qjY+X7oe(%*nuaFm7AT<&E+&D5=_vP(2rnT7xrbB}aW~0?n+cz4 zQE;PH-b};+LPVVGG(t!d4mu5nf&`=nm~gs<{@3jEawZdpVBk5+psp0;zGa=&owh%b zoHabpn6*oUQEa=IDYYPT0ALj%?}MV?CQt^#H<#>TSd=G6&lr)KmZ9X)My$ot5MYxv z^q{$~MWh)eNhJCt2z3ehzj(wWWmyr+GoEs?5lT~Cr&Y?R1vnG9)YSI!DW-4RNzPxH z1ydzdG!}+Kik5C_(@C4*$Z2x+A93=9C5w^XbEoks=BCrLWDu>TLf(;UmLPx6xJ9H^ z3XmV-p-RJ3D^fMAhD$SwB&^pB%b@Qh=M^K5h2>vJ5G10#6e>Ihp5AzC#Us#T>QmbE zj!Yz)>}{mrc1>;MBN;8Z=1yxQ=S&s%{z1CLL^6NQwgiPtdSJl(Mm6@cWB)*IJu&uQ z#{P8dJLng3<5n2hW1=qVsAHL?@E0(#k%YXaM=q`w&$yzphG{OzEWyQJkQTNz0_VN( zetW|~x7X^(0mJ;bMMfMCk9~Vc79^j%T&7zZPvI}EEW>0pU&7VMfQ)2^$ThYN6YL_) zLY@Hm0Hm47M_Gjh!69uj?%ReOVhVZXCxJvQcZomJS%E_@e%UqK#dHN4)!LmO3Vtm} zA}5%@CS?Q6Pt*}(OH)M06jYLoZy5mqhYOT+f^*{*^Aoy4QY*-;LbI}%32$puaYl5P z*-0=Du}LIHCIq*a^eZi4O*a9UJ*INgvr{=HB_v{Gszi#hosgH1qc!P*%dKYyrJ^y8 z&v?r?-2Xp%@WFjpIf-42dwqwq?*NfQWt4Xmj>4N6F^(1zihlL+$6^deD`g|GhFSIW8w9_K zSXkIV?|eft$MA{ zDf>*R#EYASsrB)O1v6>1dex;zRCVH}*}3DH&gp}Z;cUw?YO%_mLhA6^?Nf!F3sX=T zSowz7&|;ha1)n`23xr)R_ivjAAhg!x&T;j*m$+H@#K@Ac#$N1`5Hcwg_CO^^%rqca zV((A5q)Df1TIFHK%au#qtohxS4`y16)B-kRbR@Cu#p2l=li6CfGV$#P?CLaGRol+p zgr%@6UK7%qT72EUtT(v4xCnxTGOAcJ&=#9BE3clYu-D{{F#i4Ac3p6vnqchz7ixm3 z@+QL}_GDfWUR#^~TX}fJ@^wo~*DW7?$xGCIXWxAG?3;hW zc)z2dM=`WVM1V#dA}?TMtd~$?iy+9tlR*ExNDc{QsO9aWaHy?YmrvYzV)-TSd5MgX z@16g;dL4aaB#SB*F;j(n4yQ%Xf?FU}k8)^^=^}Fg1)VDZCxpfT*ok~tXgbVjC1fhmfLQb9AB%Sk2 zS%rx&saW=*uNa^Moy#G0Tm!rrK*n0wEvF+mw4A?4N{n)%u9)t41v0yE5knP=p61Hg zd|n_`M{+zNR{^OKSgaBy&jG=d10Il)Ch;aDz}sOPaAR!5H+8kH*Bm+cT|N@tI)YC4 z0rpZ)j?qOPa$MYog(0cE=5UQ~L&j!Eus1aNag9*od>_6Ar5CM^)kTu$f~Dm}e^qfr z%n8n&uP4hzc{5WIDCCUqdh80}0E!c;m#p=`>WMVlpR%zc}wbM!0$Z7&`fL1!57PG+K`it^%lnO^h z9TRldl2ycb(C=~$ZwhUVppMy1T23biv@6ROA(L$RvjaOb1F^MTPY?}pu&jka+bkcb z?WOEMNG@>B?2I6pN*NQNy_kQ0f=10%Feprzpmp7eCbK|Ut&$tpQcem&BhyxAQRA2- z&7b{M7`3O83gJ1qEAszFuwayfeM`AS3LjQnEqt9A-8v}pK^386(Ab8VjtAqeudakD zg-+W(1l$oV2kkt9MX9p=H)c7`+;3&0pC%v;aZK9Ka@o_KsjzH9l^@X)H8_%m!py9Q z&anZciDRZi#1=yv#m1q%CS~bn8kAjpjuXRR$JFM5U!}w0rl$M`W->H&j|VGSdHx#w zi8ft1`3@R~sKap7D8g=uf#EuME-^rRCEPzJu2I73r)P6`pWMobzB@^)Z_GeL+CT+n zGM%v}Ue)ts8f@E;durlKJQ8X8AmikUBymqMp7=eLT8?`;g90)wc_5)bH(u}z2>Oc^ zFYlG@WY;L}KD9{f1?N#5CTuK33*x`gcJi4b9n<-;*jc$0<$KB@6V3TOreQBpBN7XA zYAH~&NTH05&p{#?w~v4ggHmdI!Rn^gs)DLWhQeRnbhVvQpq8| zuZX#w|Eu%A#@P7;`N}3WM8Y?> zO%o*{Rbobh0B{X}Pt0lztS*v_S&V?AF~M*kf|L`?Avwe~K+70J^f?02rCxx*RX=uO z{_fBJ^8BFnlHCXH1Cn;h(%uYZj^Y=H&W;Xm{^-)jqy6EbUzne!qe?9~wjgV;4 zN;kd*h1}fFH*2OxqbA`XAp#J?@rb5&tG5j}?%kiic4d9*r)4}rap+(fQ$?96sKFbQ zvHsHL+~lGCN4?H`9lH*w0I_Rg-=zT+j(VWQe6X>2x4LC<&6`wDH-6A&*0E-3Z6w|4 zq;3YcFS+kd;SM!n;%=U)bxRc|iD77^okn)D z+$)0Zz~ z$uGt^X8(`B>qTb&=l=cQ`C>@U*8BgxUw_Odj{kXlg-?KaoP)LOhOp-3Az@4xZH8*G zP!x-(J~1*eD?=SmCKDA##S3Z*Xwjg{QuK-pL{!aS*kvbbg{W;98J`SNu-E8EF+A6a zRLZF2j-klVk@ix^T-$ZkaAR%Z$b1*R6}7OscS()wb|vqZCe@EYgfyQ|#v+*l_i1)F z9^%&j9nlT>q*L0iS_e~hN%V3wvXkAVfQI=go|75YwPHbTtRAFGG4 zQ(^GS`g|szEF8<+PXe5w10i955kk4QU70(OLj@eVKB;H(>zVr|>f_yXGpJ9hBbPi> zH-c;(smSajPtP^y zCs}*q7=W0|mAco^`*)h!i%qf!K7RD((YQIvIb{Bf*6d0ns7M*nlV{=Qyw>ra6)H6gm0U%%KJunLV6WFaCq+49dsrHl5^Q_Bot#DcnD7cj@-~@#(d>*5SkIV-o}0jvpXC zL1;{jX)V6|=u2WT(UGullB@hQ^C~KNI_gK#T{}ykifnq+uOc0&Pj9^YJ!<2>*LUA^ z)9$+3I8WH({0%ppA8UhZ+PY!v{P_8?;ZTk7lnMRxXUWk$8zO2q#~vh(iYb9E5X3fG zRUp}YOGO**#1zd{j-R394T*Nw~fu z)nww(9fuN0+|CUVnnBMQ6rMEtDp_rAsee@+L|PspJeo@ZAgK5!m{(} zu5owrwJNgoBz?ftV$>c){_3wHZNuLBj%~Cfk&a=1W9!?>dnO)Tk3`m^0tFB6+vmZ` zeuB@gz?lN(Fe6UzNO23eBTM#*%OCoeT|oZg9TEW#{pVq@JOzs_0-qC_O%TEp?;$iJoln3_9OFF1RQ2FufhnD z6oSc8y5!BwOik<6@oJ%7)@Nqax!)@VxpKY~c*O_(AnryVDERdisx$N(7 zy@iLiBzOAxc-CmRrw1q~#yy}cErVj1BJ$K;%R=Hc>TXTC*6Oy zzEdxLRbG4*)JsZUJeQJdKXSbIrQ;xuCE2SXF`$nCISt8aJJ>AU?s$7eQQ z(zyGMJGQ=eD8a`j4!!q18{>oOp5eJW?>yR_l(NOi?w8*49yIg$^IuSZ1CHJRD_INc z^Tie%6OM1%TsC*H}iPie!`_69zen>(JnlnOs%>(~GVHpM?}>Ue}+|^iSyW zx9I07$fy*v`Cc~r41b>Y%)`BzTdV*#wm|V~BvHten%>OBHI}aDiK`UKz1-wnXU%Mb zIYT3sHSI;3@fDp%{`9XHiZ*TTmo4kdrCPik3%-(z-4)|6_mv=a*B7geeUOW#E5u*8 z?6isU%C!x`@Y!UM^r}T2?wHB{hPI*VU{9oTfLJ48B}v-{X4|JsC8U?}X$bCv#T`A$ zD}PDV>vdJ%dhXm)Pn|>Z^04vTv%KKt#>TVt`m^M!zsd@>Kv1+PhDTn8zZKjU<{h?qn7IQuG5TEwPr+^TZ5$pxpe@^ln=x6sy8!+# z;wVTUvFp=Uuit3~{BzjFE?c*{Ad~MXmP$lW2)?Ld(8#If;=Tpd+g~h9<-y+kY_Wg& zpx7-HyG50&2c_!8HL3AUw&um&&W729{R{JlDh26!<$BX>X;R`LRQuGk#TND@e?OWhW^gG2O zIAk76)Zfu|FPBU4>Xx|ly(7kFr&Tc_+{}ax;?8JUB&G5RnxMo~<|X@RgHwsSZd_I1 zVT`Im9HgCsMKv%M>lzf8g)L558sXzh?=Wbo~SCcJzw((Gmu-7`_X2 zqe*y>h)Gi63Kb$alQ@MU#JTiHkTMdDB7HfHRBoc6M^?A~<%)i<*S}(Ob75ig*TOG! zWkB=z^yu-y|6fb?b<_2FYJwZhJl@uAQMl9vb5;biKTj3fo-qj6fI)>aQPFP!W5u$E zemB4|Vbao*vX!pt(veq$i~I*HZehwS^}9Bcz1ts#9U9j6vYphJ>9@|gTs)W0bmVo=!zJ0E1jJqJlk|gWm5iOf3q*u_W zk*&w-U-|pp)xStZ=3-7Hu{>N*hu!&|mmcgjs@2B-pbJ4Ed3!ZpO6!?@l=3ZpElpWWmU9VmvG~?=iA>Z4 zkeF3lot@VFWf47liX!nD_f!335??1Vu@<|2=W;s@Qi=OdSP9MS1TM6Im#T<+SuKfUw*gz zZ;hS&KCgcIo_n@lr@p;KS)^R+46%n_!l%g)TkT7{0gukr<$8$Ow6v&GL>ejyoY<-c z!->E~20%I_Pud+&t$zR7aog`sxcLM1D_?odl~=mE*5~gzboAc&-5amnoE_g$H2qS$ zSZZ%})VbZ)UU_e{FkRj~b-e)?F|D%nim|_tPM=aM?_QZ) zNvC($d9n4a>t1v6E}mTRtCY5McKxF!7?5i0?-$QAHb#ct&M8MAV&2^-?#f z6*?!Z@M?F1S6{eJvA^(RMVZ@whK~MOr1)Vl;IBtJe`4$p$SIyjL*oyM>4?&7hO9OL zBAX%JqbUR0GF&%mmJuR`x6@Y=ZLHFsL{L3w)NJTf_R-JGpD?*5s64cF$ZA3UO%%7^ z^hr)~Ou6ktF-LQOSOxg;#E-;L75}uyb!0F6TM`Ix%t7nP^6Xf8aFwaEs zi6{R`Z$Ly7O`1s`PCVjG)Xt5!%jyOrNBuG^4jC2XL%0taoTzF2S5?VmD+=fyh4&!E z%sXh_<}JJXBtfRUjIKB5=i3|zZVIR|0(Pp*&@s?aId~8|Jp%5Tc+yEZwqP$*;DC%Y z)Yf}dt3+9WPo9bx07)29iGT_%fF8>J7vOtX7aTw9MWYqEyfGkc`_7b4l2eQio9;`J zJc8?h1UNV(zANx2!V0#uuOMgiIB6w1OA9F@xh_oBuVLgsu?QYRxdJAEejU4q-kTiH zgHc-&K_;zFNkobqIscF6{}j9SDYE1f*#6}8;acu9in*)57yJ9`=ik} z+{^~W+T2lCW~Fb`WrG2|y`u5fO2UW)&_G=M6E&JpCAL0TQSWgI{@RY=)ZNim%mRQ# zrYGDsy?}a!L-70O|2uv1-Vak*K!jidq_Sj~kk6g24qBx>plH5J)O64>1DKhK7Z}5C z7ST6=d{O-r9U=c$E7CIW)QL8yXgA|JpZb-wW^Db>ci;SvhWVh_l~L`rS8`#qR`f+D ziI&z9e{n2fq|^R7k-@#BEU?boyb z83gKP=@B$)?X##-(G{=qF30sMPj5f7NIi9714Zwjk3>_d;)d4)xMmlxs- zwsa1^5YI3Nt>y?iErk%aP|1dGN722(g}0QRGXoet&o2-e&4`!11Pd~H9tA+u`;F+U z@U(T;h_0nb{Y4URd+FR5m`qe2l9Mh8*a|ce}EUIJ~lpHN{ZeB8egZD2(#BMlDbDxkFSd;<@7kgTro;@?`Cq0bz#m}W30KHrYAD9WN6}#}^)jXT5-66J1L~T# zUrRy}U`uELVGc`7K6LUfenh7;^n#o|a`yzAE7bv<(Qf>Jo}y7+l&-kmNuHsb@xDjz zNYdK8GNZp(EC!Ru?;jt}l`p>{YOF+;mZB?0^vL0IuGPN(_~ds^KmPc$kM~`nGb$DQ zls`TD$DYg1UfH|wY|?*DmOum(-8DHkH#uG!SbnlwHsGIIo$2q{)1O&|{LUzMlfE@5 zZT+tkuRd{NeK0k%BKjv0O9|P>#dDL`--WpewG|c$VI_KsElB{L0Q2??d&k*>InRB! z({$c`^6IM&*b6Jo2ZTOfc$9w z$}wpLVGaYv3U(+D7oKf-KlG(>!)_&O<(UVfn^ZIlMQ>os0(EL|@W}bGx#sX>Jx#xq zio24JmMTVIt@wJb;`wW3RhX`srN(5WHSN#2ueu~ZoSiN&<#zRtruS}M2SBwuW0srM zO0FENwlb~FOg^(vPL}J5CX=HBh2VTFnV58c#@cW$-QfKR#@BR|)iAzqWRA>qOO@v8XDr5_-o?7Ik|ey0bmCZY*o1sU7v+lrxbQ z$a2D2%cdkS%-BGee}@=%gt;>&iTefwC|Ij4!ij?uv#)uXyY=$L!&YMQz6VaZr=$J- z`Rad5 z_T6&Jfcdwb{1o6ej$Fr2AfE`FGNB@MUco9eUpxQ7Mr3FGSviDj;y znD=s7siXlhz})X{zoalq7KEY*ON5zP)r5W=1`ZA&&-Sout53u0FiV)iO%;vQDYA-* zXtHRgmJx*L5b6Pts63COy!S^Wg%HG+&b)q^QB3PnwBJ$xNOE zL6z81KS@TN>uH?-hWZrtjPwm08v>0831}ERg6`|kAOc%UG^Hls>uytkEjdzVG)lrH z6?L<*=Dhx6FN^MVhzJ@pKlb>~cPsOgWQnVZ`I1Ve>{@!FxoD;8`K+oW<_j6uDz0pP z{AJNcKemR{A&QqZ>8&jR{A)#q^5EbHx- zb-KbJtkbxMjV^hD6%BfyG11vbvV_L3VqeZH9CEe3|!>R>||-PmuZ*&ZibfZ-fXR|CSYLYYN4y0>sZ3hKWYj2|i~)SFMqGf~6uQC6uJ}8G>RgGrnZx$)>Vj zh$I!&hz{X^?6oXIP&6qAVnBA9eQDiA$zd3z;^X95GW`1)y+Ld;tl>*Wy~>Z&BevY`P-8nMU;p?g1lJ zmW}?5>2}4dB#GAPD(z|bb5svd5r7F4b{`bC5Qh*`lAtR?ki7-eDTiT0Gn*}}_pR~{ zFPhi1>P$RUNhOqqH!dFohX{FNa>js7F(UQv9f@bK-id}$1P8 zqV<$cKsyS7PhN{mIi#?oREG%!QT}znavx?_dco=}fvpP*yGltv;vdo=fUAm!jQ30(5tRJ|L>lfYp{K0(N{i zsw-$dPQeveL`j~iF#h#dVNQQc1%A>RkdRK&c_^TX61uq?jDF`8FNSDs@)YQD^_)@Y zt{lZ}&uHG>8&@bgvc2nexUWwB;_(kXaNGB5ulmW%!rW)4?~eOMr$TKI{DwxkJac4U zCm%O9RJSx<)()D9xutzUX5hRsbN6dI2hVgeSN+(^&Czr_RtQVfq>twLvHiq{ZpP}U zqKl8fK6o=R(Ff@@^I_uq^wAvgEt5|S19DYGf7(zzW7u_CjQt_AR4N+6Xx=D^BWW`+ z6h(g#J>!L#^&v`w#=US#fltG$e$MNH?CMq*6*0ckr5INm8;WJLrBMg>n;uhRE*7a>Uhvz3IT9Bi+cV zlxs2W8GZbyU#|~p=E44SE45(FG*b)Z-hRRx2X7=fL>?mMxNr|ZrbMUNEQymD?AcSmZN!D)zT;OKYBbGkA>~w|=Xcy1eJy`3sDA z^Br~5v)^T=FSbiYOcp=nC1;Rn^x6efe-VH6F4fAZcN6S%w;q+px8HY(WgfZXhp4fsaLt)*4yIOt}GuouuNEq4ZIcRj@U!bq7#Kjh&T%Pnl8+7fdpi`*tqJG z-}?HA*FSdl+UALCt`lg@xpQBged(b?Kee;(_vcagurO_N6iY5tVlO|)2`?;rd#H!G z48+EjW7oowcxLRbu@_5Lxx3VrMn;TT1SwTp!_gz7YPkImcM)G^^j@AJ^dL1N=|o9D z%Cqo1>YZ-Gvi0qyX85lA{Fd7v;s5hPy{~@m_S-!-`$o&SMYrzNwA*gK_(vry{Z6Id za$(tjhSjv~W(vID`Z*)6u8cSjW)lzE+BGbx*WXLyLo;z86^$oa@mMUrKb`(X(`;$l z{z&AGWOBdbwBqsiN~zGVJ5D!=Yu#mW`^1Q$OdUOj9Vy*zrAA%! zocM~k?JOtbB3ckzM&iPr7F1Ae!qzVkZdZ| zX-IKheatqPnJWb7l6JUppGPB$EnpDRI zVT`2@McxaqFJ2xX*5Oe=OiLFvvH@(yImioe6D>@p(aVLFSkyxa)9_K9X=D*^dnArK zeMqA*ox~$yXb32c`9Y3;bXauDP%NRJB`eO4LHk>Kng)~2c05Jj2``l;RvgQ5A9A^v zoue61HeD{H65~z!P)|zy8ebU1-HACjRca#KvuO$%)42HQWV4h^ z&P}-S!9qN`x)Qb4c3RrXids5&`&;k0X*_uA{Od+n>ZlhmL(liSbq77E{g5n&uP zX~U~g@d|&lZHmQ2eT39>fbpk;EcGU?116IWWei*j;ISx_L;nNaTsLBI^DYX?Y=TRW zMPsUE-cOqgsqZboQ4MQGt&~YN>&aMqJccuDbvgjmx~9`=$J|;o2@`e3%LX3AK%itO z|H)=kPC8vJK$y`@I4jFeWY2Efxa5GYF1^$^aEW2>-Vo(+cZ~tpaKb?F9C&BE%Tr`~2MX$v?+Fl+zsVDBs`u2uxLYoO+wUJE-%oKJ(jgBQO zVG^cbJ2cV}gW4v|FVi|uEJO^a1m=<=#!dxO%1T5UXEQl_lN7Jmf;Qqml>gtumw1YJ zKR#@BT@SUrBn?M_WlRE$aF4MAM4kZ!-^-{p5vw@dg6*qXhFmSyNr&CUlVya7(f%A& z%(>*5IsqrgYBX<^${^*^i0sWTNV3wd6o{ zoQp>j?A)$b$(3-gB|?bhOKP^>W;uVb(b9@?4k+a zvQduFkK51Y=rCzF54O1^6zfoXPEc6xl|LS21-PKJUiH@T*7DW$yc3k|>SZ%VdUmpx zr2a^A(i0WJ%lm2@z+}>iTsjkfjP}tWYK`ffnrMS&GN$ISW9BV;|FUK6ygcTV-SqBU zK8wpNRY`st*V(d#+XCZWPe8H-_mYz;BhR0xy!wWqQ_3Z%5g|Q56EYCaQD%~5W05Ue zez8_>)~oS*dZnWBv;T19p1e)>B;C#?C$7&-&QG=?SJ=e0uOM=b6Xc|W)@`;`M=xnB z4FnD)0v%>PN7Rkgy@^BbOZ%qTOlR|cAx-(WTc)HY2^m$|p$?4M5iLkw43dsiS`z3l z#C5{@13b1L$TFB1XVeSY+ged-i6m+o-VTXrtG8u~#q8F*Qx<2J5?^wa{ODBq!mz-ZOxXafZmw85i zps~~1!wkzAau2UX4*{Lh<}^v=06QkSfa$-RrnJr0!sQneAq$y*T>>!>@}*jS1A zKd_-{quaUH;f6zeJhuGpa6`vq!_a|in<*PP+lIN+)EbT)kqx8i=;>s{z7JLnAap`^ za)?$#`XN%5LRVni2gy6c7i^LFH`hKjTFrXvNA4}x)ObFYm!dl9I6f6|WAfmmxIT^_ zb1~q?%Wrt+QI!M-NOp_1>oz6rLAbnEC0K`(pZ%dRlMQ__^flYq!`w&i=}sIOj@Qh^ zgzkNr2%OFMW5DW`7l0Z;9pQ!JnGh6ZxTYyGghs(hSk;V`IeVdArR+Vud8#+}=#75v zs+QW{o#+n^XY@qRtapYlraTkY7d&Ri(4A}sMtzPi^@@~ZCo`TetRVO^ww_?As{TM# z)FU_U*;tsnanE%7cn+L=nEUwSP_ECz9Q`m-kI z^l{&gV`Hz7Pehc7wF2hm-?KAu@Fa0ewv|k97+4a_PIy=fQq;2*nkZCkKpGekc0B7v z?5gAGxOQHw9Em^$!{V5qwe5;5ep#}ZYR)$rr{{-8*BiL$Zr4vtC355Kq&xIF=3roT zeE>M^@gP1G51^6P&2-*U+>xeDkPn9RPMtIy@KtKC4Ph61J7qS#D3GQEDYn^kX)9~uLPq) zA0M}$7?!=bGz_IyFq~&*qi;s-=Y_fBGbOm1#V_ zFdoh@2)z)ATQI>0siAVQKu1%Opqng22Ad;{k8M!|#k$auAqFDJI)HH^vx#S_`!7jb ztEGkI)g?c1U4CHLS3PyI2Hy*?h6csRwCUmIMPj7^gs+GV&?TseSn2e1F6SEM*49(e z?Cw`ALS0^=zeb@p`S7*%*f^0e2z-+9`I`zorH;S-o~viGup31eFUd}(nsp#dsG0?1 zPkId#u>>cbooOC_`9#94Zk$t2Ia<>aSe*b_xCRnoes*jNzauVu^+V}F%gtO>=~h3D zgqBFkJFne1edy|qCc1iai zzHjCDspVH}d`M0GIn{w5_yAtwzl^OBQ`$#1YaZKeFEwYk({%^dW$|u?!URAwRI2QS zZq_13#209Z6Uj;pH?$2NK$rv--tnQ&0t^=}cOU$ANE<}A1c`YH2$3BZ0eXwLB$7%~ zFSHeM0}fy4fL--cH>0`ntOgMv_*~2khM8RZOwxwH34~rY>BN&D4lq{B_gfVFtIw0!B4gR9IxV-XXU;_-{n2@SV%d_F=#v@;17nY$RZDf@!Tl?p4c|orh|! zlFuLZ0tk*W-$L5gMT@BCyzbDwSy)_=RG67!9U<{WSe zTpRV%F{-%@7;G}xi6nT*Omx%BKQC~BH$Ie)83R54sP@sP6 zZfx)r*L7};m=j~OObB0c-CP?+V^&OM6f{oloGzm`OlPNsk&g&}7t@+Lp5JN0i;$wR ztfIcmc)aE~H_;iI&_#KAsitdJPjx5S)2}WyfgJySVrjj|INWo_tHPe{ru}4=KK1Ih z{@VP@7cipD(%j~r%FVOsq__21bwFR-QMzQ71pnOFSI7QEK<{c?brJ2`brED01e8Uec6iYZh zwx*?$Fj2*abeAz`&1q{{(7mCE5f25OwDos}YSZNntCkcgL)zFS8_*;A^i}iG<42 zmy7CzyzG$?sGx*F2;8&?h!Dwc$zI#Lrwz-txg+v0B}fbo*3!%a7uF9RR!VeQ!9 zg-&mRey};s7&iJb=dEXs-~Vf89*-v;I(^+wH>|{g{c$thHLdcbrnk!ZX%Gho4#dpn z)e%@9ae09erp=XGDw?@-)zGUe^`4WqiPo6bY(Xadf)BI3;l4Xx#HQn&=Fxu}XNDXmRAV7B)$v$tydN==~&& zAyzJLcWt0;b|g>vSu7C*dAi|9i)voa1-$%d)XoPso{wYsc{^g=lya+8_fdjcnrb%i z&MM1oD54$5ZcS;aeAoUl)68d^M6fNJer2`A6d;OZGWj;Nm)2-ygNO-nL6invU4N#< zVcn#ozq$jl8i0f3WDv|CWN<@z<95s|ac)pl#bWE66O}A8x!jZsw@Y+tcRZG>adu_} z%-P;qu)fDlt57EJZFL6`+xzQyGVhz3^H?qyM=9$Eb6JnN0zd0{xh$O`H81NQAaZAt zvfPu)nL4qpo5RY3Blglbz3MImd;to-crTLy zl04U}TO>is#fYAwe`Wl&5jq|u8U#BV)p{+>nUy*+hQ(+861weaqGM8NkYTiDu{*F; zm%1(BFoA&N)cOYw7hYaC@`|enEbV!>_u;KI@7<1idaHiy*c%`ImFP+;wGtKhhhPlH zh8*uQYSWJ5Xa4-yr^h}k`OJW>2NH-T2MK|}$eF|okPxDXj4<;ktA)Hx)LeIz;$)<; zh16mPcBlxern$Hzb-rY~LI@&KgoZLuRC_r(#-bm?1JYc8qlVVD?+Ij1YDfR=V-h{# zI4zk-a_lg4=`T@Kqn$04^em}UVpTLJ1ZIN+oYh}6O=z)6xlGotXlg2&3=-v%5c~h`{=T%uC+Gb96P7hp!;S#N1KS*>(B zRjg7tsAhMR3V)VU&;By zy)tn-LM)ixYfWSDAK)BqM%mA*IZblcd9N62L<0^SZF1m`C05;LEaOK0&4cWlZrJgb zQ_5sJh4$R$=zfE<{$1i&&v4)WpRwa?jc8qm62tznX){rI$ z&9mqQQY|9b4Zx5~R6s~xtmo<+EVm%?)9>|r;W2Th#pLXXsD|k*JUAxSB9c<%Eqw&K zJ&P;Pu`x+m9qK#Yi!-#iu1f-Ef%sc4^xyf?YVIE=u`{KuwwW}m?H0v|dAihE9_=0k zL6O8P#pd>)1a@gusB2}2wa77I!=xZIhQkED7p6G%xRwJQ4+U*Bafa9_m0qhR+*s-` z7LJO}w(5o+GCIkxZ7O!hq2_{gi&QoEASton_VelNNN$0c z5~dO+nY`m*h%APU9#BreLOn80A*}{q1e=iOD{b9hlfEnfJxX<$pqg*bS-ufH*({P!Z57Lm@9wmaTyd!p$J94-1(4n@RMhn1!K`FmByo*H!3q&O z(o88kxsxdK_8YQBZ)r;JO;e?69cZCnw8U+RqzX_Ff|;@D*t^K>r0@$WEC*usSOS?U z@n|ILvtSm9^8MwI=6LBoxAQjs)AMhcYcT6 zV1pv3{xmrmtS_-T$SigP-R?@*505+e^-ibrrTWuP*VXZdAMTazE&l2aH+=ix*0*oD zMR{A_RpVRV*xcke)Fq9bKsHbC9i&4>mfU;~-}afY&mgoznICj*OmqQrNX@Y1-38zQ zt`-hoEwoX@~w@0fk77;!>aaK_u{n_r$m^ zde`0FgXiau(iJbd-wl?Rq?|-lQXn3&)GQ65FvjPwyMTa~x_4!lv+4Eq^=$XX_4Mp) zI-C5h%;c?aa5DLFK0^s2Jl*BEG}Wf(a@6r@S`~o+H|jf4_gWfS*v?U>;E?4;v3HnM z81MYXA{~}kR>jFjkAhCMo$LNisXcp`jWDU^Gnw7%WFu6dZ)_;_ch`M^7+A*pz|_>E zkDi%cdz7l}bLSp>@WFVz9e#&wP|gE85y(h1-p*y|%m^MTo6C$|>{Iag*)WU|i_oZ6 zGxfY{OOr;}{b=~WFtee1qq(N-=7E377PMd8-UoZdAOO!uhkaZtPCoL;WYOa5gn2~Q zIW{pdO+C!{u~%rXQ?Gz4`rBjQ!_Eg4OjRL>N4OMq%E7sn!T}?1$xb1)xIswfIRdr> zFr*>{F%8;4HWZ7sYm*2>vdgbHmg1m-Lco6y1o#S>K1y5A2~rKTDv2$Yf)xtyZ_L)-55mkZ2*)5|X$Dh(p{0Y-AWftZ(qx7-NhvUSte1HpgJhj@PrsV6($` z#@NexeE_yg`+Xv-TN2>;?4R4!m6b>28*jYvzVCDWp5FtzAM~h}BpIZQ423a?%}KaQ zvyx@sb&6?nN?~|JKZSG=w4X3B^HnihQg{@l84al}aXsu>>VRSHu^|f00Jl7YGkPJJ z$YSJ@5N6pm!w3)hI-(zeg4s$D*`&LS;36{ZesNq3jD((nZXi| zp067Nw^159Z?zrUwt|; z91jjxm-b;|QzIuIw&q(QQJXNVCdN<3!~JB$pK+|PLSdH^Kq*q{!AvD=wZdu|#tulB zD-}oh-P4@^MV$Xae!|$Wo#}@e9^{uTb>Gs`?fu95?^$}K+IMXGnEJT<{_{VNI3kX* z&rkAQVM!7U))v`5?;HDByjE~T1R=_`)f;vqWjVSCc6q^7!7~dk#h2P-#KL9Cv+VR0aA_Nh_E9=IJ40kz((;@U?F8YFH(1ZOu?G;X zFq{OFb{c&L#!$CAImoG>r}}I$y|(tq+8MNNu(E*CsT1AEiViN4HrDWi;05xEsSBF+ zS)a$+dlRLcUn>I*ZTjE`;%k{wQX=I9PbPysU3T|TYu~TV0UgQ)-wuMCnGjaO&8mk; ziAzv&?$H;%@R!QJ|DZ*c6#{T52c9J~O_XgIz2mysbWFQ;!gVJSSB#DVdddbt?QdAv zIa13-Z`YEg#(>z%jb3&!m8`+`;uM9j{W^rpqi@xcnUtRB6?R2U zGY_?hNA4xe0~0*m82UobZa4b~zVHL@IkUNWM$PTN=iWf3hzV8S1@3=yz?A(Im61m=TCHvcSZv55NP1pZm%& z?H1_7$VQTHMotUvx7{aB0BS;}5pVa<+_}3Wrb;5JZ05|ZpKrBd9teSazVwJ!^b<4P zn`XA3_Dg=ck}HO#FvHVkxsWH-TRW|;)*C#n294Z!z1F&B4$pS--eRX+N~hFJPXl8I zG?WBZ=lqPC?{>FhKtNhnA^*0iAU0{I@A#SBop|R)yn|sj6>yIzmK=BdOjvfNsB&SK zVofj8DYfV3a+DbFPmfPbcuVmwyUCX!)k9}rtobuP!!WW3xcI6cVCJ3Vb?s;lFd zUR8R1XXoC2OZ_%_oiFtoIRg?C60y*iM4~B z^G=89ymj85qSMccNYn*1f<>t^ z82OsyY!@pH_EA9Bg{zLai>I29Jp}x60rEZ52i`XNA(#-c1JH7GUJMG3Uc}2z!yGz_ zD&QGg2p7;Y$QS4@Eec+8=h|BM9oAL2hD8^7*W{9Mfnde?ZjToOUAplvEn_AcLRe8AG;b?W1gfl_Ui*^CUbVs-RUo+1%5K7{1C zCb&hXSP0aYNeYEBA4$Z4k~4`Uok_D>StPjRLD9sigkt7wi+pSpf;Jy><`@-RX^qs% zJRTrXA}9$X#y=V>W*ZqN$vlFem!gNH3)HzGQslf=Ic;~cc6VL#W*Ezpp%gB zh)0jK0h}C$LlI{y|1!%+X|;$wMUOX;orq<qf^MW z`_U2-Z#L;nU4Z)06c&x3sw%of|Hhx4;oM};#F>iKg#44)2K#5bh1eY}6#4RSxlNhR z77#L6^q@x(TdT)GOm}8F2P`uGWFAKAPCf&D#!{8gE+IrIGZ*!NgMIkX7yQ;@v- zuo`c%`IG#PtGB2L=s(=?^1t(^}Z;*jeeqd zr>t;(M(1E$g#1?CSQwWbyj*PLKj+4EqF2IxcK)G;7~cqWWfrv)thy5?_sKLPLxZ#mb3!uq#9h( zX!}0ynJiIo-3u$T~yaqca5@9G)Som4pSlL^-3S+eO>q>aKuTLZ#NJo@m@f zx{ifn&Ij5V(*p8I|8*7zD>#C^qKm*Mq1)&hw8a8-ulO|-`;@-zhNfq%ZI#m>UPQ(h7g+|NVJTDc>ngiBFc-1n+ zTY(O{x}(ENwskIp$*xu(kN*A64L2xr`_1kF!rN}y)cT1 zujKGbla{VtQ*5^j+rQ0YvHa=F@7dhsf{`TYlAtq2!5epOeS8O?=@Y`KO+^@D2s36WgEu!WSkc zPDcNCuHnhZPm>ka<6&t3*vc1i6k%pr7ExtnmQqB?#>&9)_&Yb~Ct_J)WF(iCN(jgTKPS+K|9YsLH)L602epnMdw!Vn11AtMdz!U@DzfG>4UJpK9L zLbdvT)hBiS-(0~<8drrdk%#L*Z)vYVk~ zGQlr*AI|05E`%287Lz@fOgM#PwH~J8+AJX(TaW8S_s*^BwsL16EUZokv5!!vs*)M+ zkN<$iGX-=ppgh=Tck)b_$hTm5dl^{?V`HOSfMqI~O2zC*#ojdR0eO%HBoy`<+*dX* z9h@Q1^$?~9Z3C#JMr9F*CG3b!2xrcefv;?Qusmn(e95@@C8K5WHTA##>#zU%zyA96 zA7A~htFC(2ufFT5aB}ydQwVMnCOj*pCp9TQA^wAhnui)mnCp?gPR=Unv7Z{J>IJpv zB^^T~KJgAyABR_w-6aD0fEY1yvX3#!UQ}B2>FOmVCEI<&|iz zVG2dYz3ATEWwjR9TWzIofBW0N_;#qIj9_Z3weN--_NnnxYo)pJ*XZv%y z*V?;KyWzDrK+(B2S)MJgo#Ncw^QZp~9patX60@+pNkyO=#_nXFy9ldCOtvt$Sv~^Q z5M??DL0stq@({C|H+cUiJ~#hA9HXTLE_CgYO`#rgDjQ4J%ImjuRvl-x^G^Lky8eXm z>_-Oq3B!2eIgjd{s*?Z5e5F01Y2|vRlK-b%b*|l>+x{o2Ti^+O=FxZn2(i2~dgN0B zY4G4Y^1uL1$;O&$GQ^dww=6wZlO+eNAl^;d$bSA zCQ!j;XLm6``3W~ZSskA|bv$u%I`Hw)xeGA!#Qjr5GQHrz#(0LrCV}IEK_f}lus3cm z<@Xc5mW*D*Z07StpVO9mhu*lfG+in-UBh;3nmPI9IpQSWHZ^~FkW3vo*wNG%>pdd7bb}mG5EWYmzehehtyTW?ie83Q9p3Pft{qs_EgLT&ot=ej!`U zhY8S)egpbw1B|+JXvy3DLAy=J1-)AH3SosxA?secLJ{@XjRzp}e9rd1=QNk%kfdYWr)P`XiV-t@({lBw!{Sy8pa?uQoHvGZpo!z8m z!yJZl9;Fh8EM8a*!fd=dZ1@5kWS5dswwSfr!(ofam!7oEVkc3}cPqWzjJIM^fG&gU81We=!Dcpu9ctW<$P_WO zS!o!CR5QxAh-2AAt`6{?f1RuQyjMcuXMCcBfbwknNwB^_IseU-I)xBBGU?|i{q-+A`-cl~C)bNWFy zQ^*0Ho-9_hZnxG7RFRaLzqnx<&t|Wu{8lmLK#I4kRK99$oojgZI4+V`bA0D2BDO(> zGDkdg2&U{}XuT`MuT+xau_u=}B&s8!dT|x8j1g`U=VwiaeV+>|Eo>g`%D^_)$6Imp z;p@EBaz0)epFQN1!_e64KD1w*c%${emFG4ux9#p)tKt@dCWwd1LAkK$6YDdfT-)}B zUu?s*wz}lbrK#%;bfZ?Sw@*LxncRA@a^(XzblljKw-67Yuc|$Ue9& z|5@YjqDxem$Ni z<@(qBqp}}7y?my8w0X%~VW@f5hc^M3Pd*S9|3qM^doqlj> zs<~X5OdCSOEc)usnwGJsVXH5L*nG}-NROk*CQ~oBgsuv~nD{usQTD{wCQnE*UK(Kh z%KRIxYFW`&GFm@#@Zidz6(eSmyK#xQQLfzD!d;xKJTrRR8`1ifg|0G>K6&`s7-_K9}NIz#-HNzk6=X35GITV6{zzIOEGxb4+a4s|PdOLMIh_+tr=!H9a z+|(O2O<%htwr6Yi{>OcF@4e2%c<;>YGaY?qFZxgVL5$);#VA+y6x6}$=H}TMZEkjc zEuGG+Oy{O$Y{fpiuvZnpyFF)ApVM0#@BT%`D*8;0LZrm&tZMw$Ki1XXH=s>OwpYqt zd3`FF?wOnVa?pV#z%iGs?Be22>hUjCr?Pf=dOB$Co=DAg<|d}m0Ub57xcK9Jz3+e4 zS2o;mC>wn!TMy6K`(fB0#XcjqB<>mUPTHjSvBu>E^|yQSE z+JtXo=cT=bLK_8u@PIM&c~smV8@XV2KdYm&SW+t2RDo#*_$GM4gHLeP?oTK64E{S_ z8P@0++>r!YO`lQJ4mu80W%BTohVIMZ41|~AY1iGe=DLS3cikfgUH8Pa8$Uvj&emc8 z=Ht6gg6O-#b#I)FEB8R(jo(1_>8MRKPLiYU6M(^20Jz3eX6)#8W7i0jy z=m5PjoX-9;a^tEUts-qXj`ar9830kxyhjN*ye*6JwKSAE{*qigY?Ax5E6c1ISTMZ%(WgdD!}&rC>V)T7E6F3W%FsXLg<#c$lmNF3<_{5FRPw=) zV+ewbJTf7n+RzG#0|`Q#BT2v#Diawg5IM^vM~lXW4@dMgpX3I46w6GKfS45W*62Bp z5z)Yi-9X_Zp%mR~I`D?E>!dJF5_6^XM`j8b%{IKfag*A3Qhy|d3tLYm0uB09CvAlZ zJ()`tl2$x6{FZK1ai!vQ2nitk92i^t^aTBLLw{d^ud+2g&w)hakD#ZB|>ug%Gnw)%*^SE*!UTzZPYa z1{g^tP@`~zY^2^eDF|X0vC;fTdZXWr3CEuR5P|drCc_N=CQ=G?t?U~2Q?(<9|hjQyAblK8TPs^P)Dp^ZWe)e{Q9z0 z3_{kx#V6|5xw5^JXTbxet6|=u!{Vt?mHy%&Uk_4oOH1T(mOc0RdEE&z$xAU0agbd? z+&gm#;UZI;FTiCqR|=u7N*rD)%$Obtm>IIWu_VR2JC0W^Y36E`+4`_r^{nz-IY&`y zc$D*{xyQ4!g=#YEVg;)*v0kc(0z_?u%lY%vlPqLV(;w4mut$zEMMtU@__iOly_vJ?N|&JP$KLL^f%mNR@?T;oNQ|cuG#;h ziRSq8&OZ9#hc0{liS5|~tAC)`IkJABB!gs_`cuZi`)|JPHGk<86S-KNTxipcr97Xs zu`uC&H%g--gyT7+L{Z*M8)ofv$#CMU-di(Ic{U`A7fMKDAD_~7c zJsjxdj)^_=ttih{M+V#^9v-RUIF9+&rS|Sf_w4!fn;lhlFDp;-wofRhztWmB3Cc)t z6hn{eT33q*fxJMSqdiHaX5KoG)MFdzn*Q} zjZ;G$aEk0Yrh+6j&rz~9VZ8;E6XG{s4$D!cd&+{wb8aJ75(si z{)XZq5@0SrHfw_oUsi?n4|>k+SCfHll+u+>`;VY;PNgT#E~}-P1LGN71gtDTB{BWB ziR(}7j^d)q4dLJgg%qo?r`R)V@3=c6%C1x1wDiH{WGdTK#^su7-ku?Tr3I~tY{E%4 zo8wM_3c4QL3dEiC+Dt8JykySG27vTqt*Uq5Fc?2Hm#9zoC`TRoV5f9*aoVJ`=3;i{ zPSCx|m|8Zp#D^Rs4f$_lsx&U^Lt+*q8Eq343CTo!-ZQpWc1Ma`u*ELC2Km-w|JeD( zX<&Ds{kuF2+0LK!i@iO>kMPWI-tLVowV!(Gt#5tmtv~gNSHJobuYTmCFMs(*U#{L} zC68{T{b468RtOX)jB+XL41)CL(WG_!l%}0N@yr2bg9FS;G3*Te^v2PIed06;wHJ)K zU#97|KBcy3`_-S={$m<{`A2&fj!jx8PVY3fnfdq6cIr51+e`<8c2F9fP3D@^izm4p zi$xf$LbMv;Wrd~{Z`_s!&D%0IIW`~IY=%*;%`@FD|XS5 zr`eWzZP96EE8E|smD%rQXIJN>(8pt6Q735q4Nsnz5A9-f==6nl>!}MTGMwj}Xqm5% zXQe|gk{+!}=Z?v_TG_0eTIRIm)_$A4;Dhj;FOfBMACZsOQWNvnxKDk_5EI|G>VhXp|6}xN!5>-O?pgG2$EmQUu@vYw(g>8eR@qdC#tN+omgwTb3p z%qw_Su^UXR!Ni){>P|E_LaE$Z7*=w*N^S-Y#321PsmBHi&Y@&dfGbP`&Q_m-4mE8} z)e}k5i_{0psfSLMf(-crq7Q)}$pod9>o(#qY4&oHSV(!KvYkzM@GejeN5`FQyB<)B ztR%PK`y;;t2BbZ3aBDOJ#u@esH|rH>Mnh@ZQ_mcuSA|xZUgatYdX*0P@hb5kqZ+4z zvZ0_e2GUlChc%wlJjALpJ*#kBUEIge&tr^36ydZoe#&m-9H=sAx% z&dnj*9k6U=H=r-{^SL1_DD3t^i2}%P4cH`30|yfaqiETMmC1H2ws76% zg6rl73)2a&xjx$~;hfA|(xE2Aa8AvU#efpA{U>unj%*lL>h9Fy$yqbKI6KU1PPx9= zzoe}vn6pKgewU9T6Ut!HegO^RW$NAJ1bkloDZxbKAeg3g)ms)}DQY9Yd5L=u6bU25y4o1zb$kK%08V4>_s0A9z z8?xre)RD&?=qi!PI7JY~J7$42jBy~1EK3jN#Lxbj2TV>kC9cUirE_eTf*bKey2qi2 zb40o{z}x(XLPRVLXl$cC%Zd0ApNu?S{E<~3bz{^O=|MCiQUCDRNH?P^^zpEfpf>s< ztiICmMX_iI!%C~tzGxWaFUY_Mivn13;vPfBTE<&`X^WFZoo95}C%D$pXUqKoC!kFl z0T{0fi#D5zg_dW@ZZ#lA#dxr*@c|ske=SiP`4!+373&1J!O{ZeAv=w{FAo?V=wbpR zhw&^5myW(B7$=+_(f6et$#CJ@qPvrbmIO2|NAL!1LA?ZKnrA>zNWG>tYz1C}r$#RX zPc0`ADjP5^q($;IIz;(&G+^aYZZz|!yrIwWt% zi3FG>=cgOeNzOwzA|6cv;S1Pn^b1QMFcuV8;ccNMexuYJ{(!e9_8h%w+cjxUSY>HW zhUZB1K{QOUC@QSf)q)K(^qg^tlhh`g@gpe`7k)5ZqkNHBEOs;K^s3k%-(zP3i-=i; z5-i~9VA3_r5Kz5SH{sZ!?hEu*Kx$&_Z1B)>ja&oh

                                                                                                                                                                                                                                                                                            J0sC^*tvYt+D^_1Y@1prUk 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 diff --git a/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.woff b/src/WebExpress.WebUI/Assets/fonts/fa-brands-400.woff deleted file mode 100644 index 277ab65bb454ce4dd64d2cf6a5bf42b06e8c1e93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92136 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 z

                                                                                                                                                                                                                                                                                            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