diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml
new file mode 100644
index 0000000..e427ab2
--- /dev/null
+++ b/.github/workflows/generate-docs.yml
@@ -0,0 +1,52 @@
+name: Generate and Deploy Documentation
+
+on:
+ push:
+ branches:
+ - main
+
+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 52cedf9..a8d1939 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,45 @@

# 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.WebApp
-WebExpress.WebApp is part of the WebExpress family. Provides a business application template for WebExpress applications.
+`WebExpress.WebApp` is part of the WebExpress family. Provides a business application template for `WebExpress` applications.
# 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)
+- [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/)
+- [WebExpress.WebApp API Documentation](https://reneschwarzer.github.io/WebExpress.WebApp/)
+- [WebExpress.WebIndex API Documentation](https://reneschwarzer.github.io/WebExpress.WebIndex/)
+
+# 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.
-## Tutorials
- [HelloWorld](https://github.com/ReneSchwarzer/WebExpress.Tutorial.HelloWorld#readme)
+- [WebApp](https://github.com/ReneSchwarzer/WebExpress.Tutorial.WebApp#readme)
+- [WebIndex](https://github.com/ReneSchwarzer/WebExpress.Tutorial.WebIndex#readme)
# Tags
-#WebExpress #BusinessApplication
\ No newline at end of file
+#WebApp #WebExpress #BusinessApplication #DotNet #NETCore
\ No newline at end of file
diff --git a/docs/api/toc.yml b/docs/api/toc.yml
new file mode 100644
index 0000000..20c32af
--- /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 0000000..c0909c9
Binary files /dev/null and b/docs/assets/webexpress.ico differ
diff --git a/docs/assets/webexpress.svg b/docs/assets/webexpress.svg
new file mode 100644
index 0000000..e9243f5
--- /dev/null
+++ b/docs/assets/webexpress.svg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+ template
+
+
+ Tabelle.2
+
+
+
+ Tabelle.35
+
+
+
+
diff --git a/docs/docfx.json b/docs/docfx.json
new file mode 100644
index 0000000..4260351
--- /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.WebApp/*.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.WebApp",
+ "_appName": "WebExpress.WebApp",
+ "_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 0000000..51771b6
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,28 @@
+
+
+# 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.WebApp
+`WebExpress.WebApp` is part of the WebExpress family. Provides a business application template for `WebExpress` applications.
+
+# Download
+The current binaries are available for download [here](https://github.com/ReneSchwarzer/WebExpress/releases).
+
+# Tags
+#WebApp #WebExpress #BusinessApplication #DotNet #NETCore
diff --git a/docs/template/dashboard.html.tmpl b/docs/template/dashboard.html.tmpl
new file mode 100644
index 0000000..0288fe8
--- /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}}
+
+
+
+
+ {{#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 0000000..b0b8c1f
--- /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 0000000..d5c4867
--- /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 0000000..a00ab75
--- /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 0000000..650bed9
--- /dev/null
+++ b/docs/toc.yml
@@ -0,0 +1,8 @@
+- name: Home
+ href: index.md
+- name: API Documentation
+ href: api/WebExpress.WebApp.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 0000000..77c2af0
--- /dev/null
+++ b/docs/tutorials.md
@@ -0,0 +1,17 @@
+
+
+# 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)
+- [WebIndex](https://github.com/ReneSchwarzer/WebExpress.Tutorial.WebIndex#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 0000000..e885c63
--- /dev/null
+++ b/docs/user-guide.md
@@ -0,0 +1,17 @@
+
+
+# User guide
+Welcome to the `WebExpress.WebApp` User Guide. This guide will help you get started with `WebExpress.WebApp` and make the most out of its
+features. Follow the links below to begin your journey.
+
+# Getting started
+To get started with `WebExpress.WebApp`, 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/)
+- [WebExpress.WebApp API Documentation](https://reneschwarzer.github.io/WebExpress.WebApp/)
+- [WebExpress.WebIndex API Documentation](https://reneschwarzer.github.io/WebExpress.WebIndex/)
+
+We hope you enjoy using `WebExpress.WebApp` and find it valuable for your projects. Happy coding!
diff --git a/src/WebExpress.WebApp.Test/Fixture/AssertExtensions.cs b/src/WebExpress.WebApp.Test/Fixture/AssertExtensions.cs
new file mode 100644
index 0000000..5139bb3
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/Fixture/AssertExtensions.cs
@@ -0,0 +1,89 @@
+using System.Text.RegularExpressions;
+using WebExpress.WebCore.WebHtml;
+
+namespace WebExpress.WebApp.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?.ToString());
+ 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)
+ {
+ if (string.IsNullOrWhiteSpace(expected) && string.IsNullOrWhiteSpace(actual))
+ {
+ return true;
+ }
+ else if (!string.IsNullOrWhiteSpace(expected) && string.IsNullOrWhiteSpace(actual))
+ {
+ return false;
+ }
+ else if (string.IsNullOrWhiteSpace(expected) && !string.IsNullOrWhiteSpace(actual))
+ {
+ return false;
+ }
+
+ 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.WebApp.Test/Fixture/NonParallelTestsCollection.cs b/src/WebExpress.WebApp.Test/Fixture/NonParallelTestsCollection.cs
new file mode 100644
index 0000000..bf57e89
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/Fixture/NonParallelTestsCollection.cs
@@ -0,0 +1,11 @@
+namespace WebExpress.WebApp.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.WebApp.Test/Fixture/UnitTestControlFixture.cs b/src/WebExpress.WebApp.Test/Fixture/UnitTestControlFixture.cs
new file mode 100644
index 0000000..5e16f32
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/Fixture/UnitTestControlFixture.cs
@@ -0,0 +1,245 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using System.Globalization;
+using System.Net;
+using System.Reflection;
+using System.Text;
+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.WebPage;
+using WebExpress.WebCore.WebPlugin;
+using WebExpress.WebCore.WebUri;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.Fixture
+{
+ ///
+ /// A fixture class for unit tests, providing various mock objects and utility methods.
+ ///
+ public partial class UnitTestControlFixture : IDisposable
+ {
+ private static readonly string[] _separator = ["\r\n", "\r", "\n"];
+
+ ///
+ /// Initializes a new instance of the class and boot the component manager.
+ ///
+ public UnitTestControlFixture()
+ {
+ }
+
+ ///
+ /// Create a fake server context.
+ ///
+ /// The server context.
+ public static IHttpServerContext CreateHttpServerContextMock()
+ {
+ return new HttpServerContext
+ (
+ new RouteEndpoint("localhost"),
+ [],
+ "",
+ Environment.CurrentDirectory,
+ Environment.CurrentDirectory,
+ Environment.CurrentDirectory,
+ new RouteEndpoint("/server"),
+ CultureInfo.GetCultureInfo("en"),
+ new Log() { LogMode = LogMode.Off },
+ null
+ );
+ }
+
+ ///
+ /// Create a component hub.
+ ///
+ /// The component hub.
+ public static ComponentHub CreateComponentHubMock()
+ {
+ var ctorComponentHub = typeof(ComponentHub).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 CreateRequestMock(string content = "", string uri = "")
+ var context = CreateHttpContextMock(content);
+
+ var request = context.Request;
+
+ if (!string.IsNullOrEmpty(uri))
+ {
+ var uriProperty = typeof(Request).GetProperty("Uri", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ uriProperty.SetValue(request, new UriEndpoint(uri));
+ }
+
+ return request;
+ }
+
+ ///
+ /// Create a fake http context.
+ ///
+ /// The content.
+ /// A fake http context for testing.
+ public static WebCore.WebMessage.HttpContext CreateHttpContextMock(string content = "")
+ {
+ 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
+ {
+ Headers = new HeaderDictionary
+ {
+ ["Host"] = "localhost",
+ ["Connection"] = "keep-alive",
+ ["ContentType"] = "text/html",
+ ["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",
+ ["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"
+ };
+
+ 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 context = new WebCore.WebMessage.HttpContext(featureCollection, CreateHttpServerContextMock());
+
+ return context;
+ }
+
+ ///
+ /// Creates a mock render context for unit testing.
+ ///
+ /// 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 CreateRenderContextMock(IApplicationContext applicationContext = null, IEnumerable scopes = null)
+ {
+ var request = CreateRequestMock();
+
+ return new RenderControlContext(null, CreatePageContextMock(applicationContext, scopes), request);
+ }
+
+ ///
+ /// 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 static PageContext CreatePageContextMock(IApplicationContext applicationContext = null, IEnumerable scopes = null)
+ var ctorPageContext = typeof(PageContext).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, [], null);
+
+ var pageContext = (PageContext)ctorPageContext.Invoke([]);
+ var applicationContextProperty = typeof(PageContext).GetProperty("ApplicationContext", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ applicationContextProperty.SetValue(pageContext, applicationContext);
+
+ var scopesProperty = typeof(PageContext).GetProperty("Scopes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ scopesProperty.SetValue(pageContext, scopes);
+
+ return pageContext;
+ }
+
+ ///
+ /// 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 static string GetEmbeddedResource(string fileName)
+ {
+ var assembly = typeof(UnitTestControlFixture).Assembly;
+ var resourceName = assembly.GetManifestResourceNames()
+ .FirstOrDefault(name => name.EndsWith(fileName, StringComparison.OrdinalIgnoreCase));
+
+ using var stream = assembly.GetManifestResourceStream(resourceName);
+ using var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
+ var data = memoryStream.ToArray();
+
+ return Encoding.UTF8.GetString(data);
+ }
+
+ ///
+ /// Release of unmanaged resources reserved during use.
+ ///
+ public void Dispose()
+ {
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestApplication.cs b/src/WebExpress.WebApp.Test/TestApplication.cs
new file mode 100644
index 0000000..087b612
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestApplication.cs
@@ -0,0 +1,44 @@
+using WebExpress.WebCore.WebApplication;
+using WebExpress.WebCore.WebAttribute;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy application for testing purposes.
+ ///
+ [Name("TestApplication")]
+ [Description("application.description")]
+ [Icon("/assets/img/Logo.png")]
+ [ContextPath("/app")]
+ [AssetPath("/asset")]
+ [DataPath("/data")]
+ public sealed class TestApplication : IApplication
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// 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.");
+ }
+ }
+
+ ///
+ /// 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.WebApp.Test/TestFragmentGeneral.cs b/src/WebExpress.WebApp.Test/TestFragmentGeneral.cs
new file mode 100644
index 0000000..c05acea
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestFragmentGeneral.cs
@@ -0,0 +1,26 @@
+using WebExpress.WebApp.WebScope;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebFragment;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy fragment for testing purposes.
+ ///
+ [Section()]
+ [Scope]
+ public sealed class TestFragmentGeneral : FragmentControlDropdownItemLink
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TestFragmentGeneral(IFragmentContext fragmentContext)
+ : base(fragmentContext)
+ {
+ Add(new ControlText() { Text = "Hello World" });
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestFragmentPageA.cs b/src/WebExpress.WebApp.Test/TestFragmentPageA.cs
new file mode 100644
index 0000000..917f40c
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestFragmentPageA.cs
@@ -0,0 +1,26 @@
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebFragment;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy fragment for testing purposes.
+ ///
+ [Section()]
+ [Section()]
+ [Scope]
+ public sealed class TestFragmentPageA : FragmentControlPanel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TestFragmentPageA(IFragmentContext fragmentContext)
+ : base(fragmentContext)
+ {
+ Add(new ControlText() { Text = "Hello World" });
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestFragmentPageB.cs b/src/WebExpress.WebApp.Test/TestFragmentPageB.cs
new file mode 100644
index 0000000..69bdafd
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestFragmentPageB.cs
@@ -0,0 +1,25 @@
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebFragment;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy fragment for testing purposes.
+ ///
+ [Section()]
+ [Scope]
+ public sealed class TestFragmentPageB : FragmentControlPanel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TestFragmentPageB(IFragmentContext fragmentContext)
+ : base(fragmentContext)
+ {
+ Add(new ControlText() { Text = "Hello World" });
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestPageA.cs b/src/WebExpress.WebApp.Test/TestPageA.cs
new file mode 100644
index 0000000..1e31546
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestPageA.cs
@@ -0,0 +1,50 @@
+using WebExpress.WebApp.WebPage;
+using WebExpress.WebApp.WebScope;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebPage;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy class for testing purposes.
+ ///
+ [Title("webindex:pagea.label")]
+ [Segment("pagea", "webindex:homepage.label")]
+ [Scope]
+ public sealed class TestPageA : IPage, IScopeGeneral
+ {
+ ///
+ /// Returns or sets the page context.
+ ///
+ public IPageContext PageContext { get; private set; }
+
+ ///
+ /// Initialization of the page. Here, for example, managed resources can be loaded.
+ ///
+ /// The context of the page.
+ public TestPageA(IPageContext pageContext)
+ {
+ PageContext = pageContext;
+
+ // test the injection
+ if (pageContext == null)
+ {
+ throw new ArgumentNullException(nameof(pageContext), "Parameter cannot be null or empty.");
+ }
+ }
+
+ ///
+ /// Processing of the page.
+ ///
+ /// The context for rendering the page.
+ /// The visual tree control to be processed.
+ public void Process(IRenderContext renderContext, VisualTreeWebApp visualTree)
+ {
+ // test the context
+ if (renderContext == null)
+ {
+ throw new ArgumentNullException(nameof(renderContext), "Parameter cannot be null or empty.");
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestPageB.cs b/src/WebExpress.WebApp.Test/TestPageB.cs
new file mode 100644
index 0000000..e31eabe
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestPageB.cs
@@ -0,0 +1,50 @@
+using WebExpress.WebApp.WebPage;
+using WebExpress.WebApp.WebScope;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebPage;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy class for testing purposes.
+ ///
+ [Title("webindex:pagea.label")]
+ [Segment("pageb", "webindex:homepage.label")]
+ [Scope]
+ public sealed class TestPageB : IPage, IScopeGeneral
+ {
+ ///
+ /// Returns or sets the page context.
+ ///
+ public IPageContext PageContext { get; private set; }
+
+ ///
+ /// Initialization of the page. Here, for example, managed resources can be loaded.
+ ///
+ /// The context of the page.
+ public TestPageB(IPageContext pageContext)
+ {
+ PageContext = pageContext;
+
+ // test the injection
+ if (pageContext == null)
+ {
+ throw new ArgumentNullException(nameof(pageContext), "Parameter cannot be null or empty.");
+ }
+ }
+
+ ///
+ /// Processing of the page.
+ ///
+ /// The context for rendering the page.
+ /// The visual tree control to be processed.
+ public void Process(IRenderContext renderContext, VisualTreeWebApp visualTree)
+ {
+ // test the context
+ if (renderContext == null)
+ {
+ throw new ArgumentNullException(nameof(renderContext), "Parameter cannot be null or empty.");
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestPlugin.cs b/src/WebExpress.WebApp.Test/TestPlugin.cs
new file mode 100644
index 0000000..fe75d50
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestPlugin.cs
@@ -0,0 +1,31 @@
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebPlugin;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy plugin for testing purposes.
+ ///
+ [Name("TestPlugin")]
+ [Description("plugin.description")]
+ [Icon("/assets/img/Logo.png")]
+ [Application()]
+ public sealed class TestPlugin : IPlugin
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The plugin context.
+ private TestPlugin(IPluginContext pluginContext)
+ {
+
+ }
+
+ ///
+ /// Called when the plugin starts working. The call is concurrent.
+ ///
+ public void Run()
+ {
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestSectionAppPreferencesItem.cs b/src/WebExpress.WebApp.Test/TestSectionAppPreferencesItem.cs
new file mode 100644
index 0000000..6bcc909
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestSectionAppPreferencesItem.cs
@@ -0,0 +1,23 @@
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebFragment;
+using WebExpress.WebUI.WebFragment;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy fragment for testing purposes.
+ ///
+ [Section]
+ public sealed class TestFragmentSectionAppPreferencesItem : FragmentControlDropdownItemLink
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TestFragmentSectionAppPreferencesItem(IFragmentContext fragmentContext)
+ : base(fragmentContext)
+ {
+ Text = "TestFragmentSectionAppPreferencesItem";
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestThemeA.cs b/src/WebExpress.WebApp.Test/TestThemeA.cs
new file mode 100644
index 0000000..aafc1d6
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestThemeA.cs
@@ -0,0 +1,22 @@
+using WebExpress.WebApp.WebTheme;
+using WebExpress.WebCore.WebAttribute;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy theme for testing.
+ ///
+ [Name("TestThemeA")]
+ [Description("A dummy theme for testing.")]
+ [Image("webexpress.webcore.test.testthemea.png")]
+ public sealed class TestThemeA : IThemeWebApp
+ {
+ ///
+ /// Returns the text color for the theme.
+ ///
+ ///
+ /// A string representing the text color in hexadecimal format.
+ ///
+ public static string TextColor => "000000";
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/TestThemeB.cs b/src/WebExpress.WebApp.Test/TestThemeB.cs
new file mode 100644
index 0000000..513a805
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/TestThemeB.cs
@@ -0,0 +1,20 @@
+using WebExpress.WebApp.WebTheme;
+using WebExpress.WebCore.WebAttribute;
+
+namespace WebExpress.WebApp.Test
+{
+ ///
+ /// A dummy theme for testing.
+ ///
+ [Name("TestThemeB")]
+ public sealed class TestThemeB : IThemeWebApp
+ {
+ ///
+ /// Returns the text color for the theme.
+ ///
+ ///
+ /// A string representing the text color in hexadecimal format.
+ ///
+ public static string TextColor => "FFFFFF";
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/UnitTest.cs b/src/WebExpress.WebApp.Test/UnitTest.cs
deleted file mode 100644
index 9e1b74f..0000000
--- a/src/WebExpress.WebApp.Test/UnitTest.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using WebExpress.WebCore;
-using Xunit.Abstractions;
-
-namespace WebExpress.WebApp.Test
-{
- public class UnitTest
- {
- public ITestOutputHelper Output { get; private set; }
-
- public UnitTest(ITestOutputHelper output)
- {
- Output = output;
- }
-
- [Fact]
- public void StartServer()
- {
- //Process.Start("http://localhost/");
-
- WebEx.Main([]);
- }
- }
-}
diff --git a/src/WebExpress.WebApp.Test/WebApiControl/UnitTestControlApiTable.cs b/src/WebExpress.WebApp.Test/WebApiControl/UnitTestControlApiTable.cs
new file mode 100644
index 0000000..e034585
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebApiControl/UnitTestControlApiTable.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebApiControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebApiControl
+{
+ ///
+ /// Tests the api table control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlApiTable
+ {
+ ///
+ /// Tests the id property of the api table control.
+ ///
+ [Theory]
+ [InlineData(null, @"
")]
+ [InlineData("id", @"
")]
+ public void Id(string id, 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 control = new ControlApiTable(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppContent.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppContent.cs
new file mode 100644
index 0000000..00cc8b3
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppContent.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app content control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppContent
+ {
+ ///
+ /// Tests the id property of the web app content control.
+ ///
+ [Theory]
+ [InlineData(null, @"*
")]
+ [InlineData("id", @"*
")]
+ public void Id(string id, 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 control = new ControlWebAppContent(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppFooter.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppFooter.cs
new file mode 100644
index 0000000..0b79c16
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppFooter.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app footer control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppFooter
+ {
+ ///
+ /// Tests the id property of the web app footer control.
+ ///
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("id", null)]
+ public void Id(string id, 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 control = new ControlWebAppFooter(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeader.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeader.cs
new file mode 100644
index 0000000..3baaa37
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeader.cs
@@ -0,0 +1,114 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeader
+ {
+ ///
+ /// Tests the id property of the web app header control.
+ ///
+ [Theory]
+ [InlineData(null, @"")]
+ [InlineData("id", @"")]
+ 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 ControlWebAppHeader(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+
+ ///
+ /// Tests the text color property of the web app header control.
+ ///
+ [Theory]
+ [InlineData(TypeColorNavbar.Primary, @"")]
+ [InlineData(TypeColorNavbar.Secondary, @"")]
+ [InlineData(TypeColorNavbar.Info, @"")]
+ [InlineData(TypeColorNavbar.Success, @"")]
+ [InlineData(TypeColorNavbar.Warning, @"")]
+ [InlineData(TypeColorNavbar.Danger, @"")]
+ [InlineData(TypeColorNavbar.Light, @"")]
+ [InlineData(TypeColorNavbar.Dark, @"")]
+ [InlineData(TypeColorNavbar.White, @"")]
+ [InlineData(TypeColorNavbar.Transparent, @"")]
+ public void TextColor(TypeColorNavbar textColor, string expected)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var context = UnitTestControlFixture.CrerateRenderContextMock();
+ var visualTree = new VisualTreeControl(componentHub, context.PageContext);
+ var control = new ControlWebAppHeader()
+ {
+ TextColor = new PropertyColorNavbar(textColor)
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+
+ ///
+ /// Tests the fixed property of the web app header control.
+ ///
+ [Theory]
+ [InlineData(TypeFixed.None, @"")]
+ [InlineData(TypeFixed.Top, @"")]
+ [InlineData(TypeFixed.Bottom, @"")]
+ public void Fixed(TypeFixed fixedProperty, string expected)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var context = UnitTestControlFixture.CrerateRenderContextMock();
+ var visualTree = new VisualTreeControl(componentHub, context.PageContext);
+ var control = new ControlWebAppHeader()
+ {
+ Fixed = fixedProperty
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+
+ ///
+ /// Tests the sticky property of the web app header control.
+ ///
+ [Theory]
+ [InlineData(TypeSticky.None, @"")]
+ [InlineData(TypeSticky.Top, @"")]
+ public void Sticky(TypeSticky sticky, string expected)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var context = UnitTestControlFixture.CrerateRenderContextMock();
+ var visualTree = new VisualTreeControl(componentHub, context.PageContext);
+ var control = new ControlWebAppHeader()
+ {
+ Sticky = sticky
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigation.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigation.cs
new file mode 100644
index 0000000..e4e9dcc
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigation.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header navigation control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderAppNavigation
+ {
+ ///
+ /// Tests the id property of the web app header navigation control.
+ ///
+ [Theory]
+ [InlineData(null, @"*
")]
+ [InlineData("id", @"*
")]
+ public void Id(string id, 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 control = new ControlWebAppHeaderAppNavigation(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigator.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigator.cs
new file mode 100644
index 0000000..7e97b7b
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppNavigator.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header app navigator control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderAppNavigator
+ {
+ ///
+ /// Tests the id property of the web app header app navigator control.
+ ///
+ [Theory]
+ [InlineData(null, @"*
")]
+ [InlineData("id", @"*
")]
+ public void Id(string id, 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 control = new ControlWebAppHeaderAppNavigator(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppTitle.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppTitle.cs
new file mode 100644
index 0000000..38bcc29
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderAppTitle.cs
@@ -0,0 +1,35 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header app title control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderAppTitle
+ {
+ ///
+ /// Tests the id property of the web app header app title control.
+ ///
+ [Theory]
+ [InlineData(null, @"TestApplication ")]
+ [InlineData("id", @"TestApplication ")]
+ public void Id(string id, string expected)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var context = UnitTestControlFixture.CrerateRenderContextMock(componentHub?.ApplicationManager.Applications.FirstOrDefault());
+ var visualTree = new VisualTreeControl(componentHub, context.PageContext);
+ var control = new ControlWebAppHeaderAppTitle(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderHelp.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderHelp.cs
new file mode 100644
index 0000000..88452de
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderHelp.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header help control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderHelp
+ {
+ ///
+ /// Tests the id property of the web app header help control.
+ ///
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("id", null)]
+ public void Id(string id, 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 control = new ControlWebAppHeaderHelp(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderQuickCreate.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderQuickCreate.cs
new file mode 100644
index 0000000..36b7a3b
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderQuickCreate.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header quick create control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderQuickCreate
+ {
+ ///
+ /// Tests the id property of the web app header quick create control.
+ ///
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("id", null)]
+ public void Id(string id, 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 control = new ControlWebAppHeaderQuickCreate(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderSettings.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderSettings.cs
new file mode 100644
index 0000000..ca8269c
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeaderSettings.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app header settings control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeaderSettings
+ {
+ ///
+ /// Tests the id property of the web app header settings control.
+ ///
+ [Theory]
+ [InlineData(null, "*
")]
+ [InlineData("id", "*
")]
+ public void Id(string id, 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 control = new ControlWebAppHeaderSettings(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeadline.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeadline.cs
new file mode 100644
index 0000000..b811564
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppHeadline.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app headline control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppHeadline
+ {
+ ///
+ /// Tests the id property of the web app headline control.
+ ///
+ [Theory]
+ [InlineData(null, @"")]
+ [InlineData("id", @"")]
+ public void Id(string id, 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 control = new ControlWebAppHeadline(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppProperty.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppProperty.cs
new file mode 100644
index 0000000..9f1ffe9
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppProperty.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app property control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppProperty
+ {
+ ///
+ /// Tests the id property of the web app property control.
+ ///
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("id", null)]
+ public void Id(string id, 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 control = new ControlWebAppProperty(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppSidebar.cs b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppSidebar.cs
new file mode 100644
index 0000000..a9f5b03
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebControl/UnitTestControlWebAppSidebar.cs
@@ -0,0 +1,36 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebControl
+{
+ ///
+ /// Tests the web app sidebar control.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestControlWebAppSidebar
+ {
+ ///
+ /// Tests the id property of the web app sidebar control.
+ ///
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("id", null)]
+ public void Id(string id, 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 control = new ControlWebAppHeaderQuickCreate(id)
+ {
+ };
+
+ // test execution
+ var html = control.Render(context, visualTree);
+
+ AssertExtensions.EqualWithPlaceholders(expected, html);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebExpress.WebApp.Test.csproj b/src/WebExpress.WebApp.Test/WebExpress.WebApp.Test.csproj
index c945db7..270a849 100644
--- a/src/WebExpress.WebApp.Test/WebExpress.WebApp.Test.csproj
+++ b/src/WebExpress.WebApp.Test/WebExpress.WebApp.Test.csproj
@@ -1,25 +1,27 @@

- net8.0
+ net9.0
enable
false
true
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
+
+
+
-
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
diff --git a/src/WebExpress.WebApp.Test/WebFragment/UnitTestFragmentManager.cs b/src/WebExpress.WebApp.Test/WebFragment/UnitTestFragmentManager.cs
new file mode 100644
index 0000000..47a6e84
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebFragment/UnitTestFragmentManager.cs
@@ -0,0 +1,125 @@
+using System.Reflection;
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebScope;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore.WebApplication;
+using WebExpress.WebCore.WebFragment;
+using WebExpress.WebCore.WebScope;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.Test.WebFragment
+{
+ ///
+ /// Test the fragment manager.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestFragmentManager
+ {
+ ///
+ /// Test the id property of the fragment manager.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(TestFragmentPageA), "webexpress.webapp.test.testfragmentpagea")]
+ 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 get fragments function of the fragment manager.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentPrimary), typeof(TestPageA), 1, @"")]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentPrimary), typeof(IScopeGeneral), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentPrimary), typeof(IScope), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionContentPrimary), typeof(TestPageA), 1, @"")]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionContentPrimary), typeof(IScopeGeneral), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionContentPrimary), typeof(IScope), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(IFragmentBase), typeof(SectionContentPrimary), typeof(TestPageA), 1, @"")]
+ [InlineData(typeof(TestApplication), typeof(IFragmentBase), typeof(SectionContentPrimary), typeof(IScopeGeneral), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(IFragmentBase), typeof(SectionContentPrimary), typeof(IScope), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionAppNavigationPrimary), typeof(TestPageA), 1, @"")]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionAppNavigationPrimary), typeof(IScopeGeneral), 1, @"Hello World
")]
+ [InlineData(typeof(TestApplication), typeof(IFragmentControl), typeof(SectionAppNavigationPrimary), typeof(IScope), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentSecondary), typeof(TestPageB), 1, @"")]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentSecondary), typeof(IScopeGeneral), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentSecondary), typeof(IScope), 0, null)]
+ [InlineData(typeof(TestApplication), typeof(FragmentControlPanel), typeof(SectionContentPrimary), typeof(TestPageB), 0, null)]
+
+ public void GetFragments(Type applicationType, Type fragmentType, Type sectionType, Type scopeType, int count, string expected)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault();
+ var renderContext = UnitTestControlFixture.CrerateRenderContextMock(application, [scopeType]);
+ var visualTree = new VisualTreeControl(componentHub, renderContext.PageContext);
+
+ // reflection to get GetFragments method
+ var fragmentManagerType = componentHub.FragmentManager.GetType();
+ var getFragmentsMethod = fragmentManagerType.GetMethod
+ (
+ "GetFragments",
+ BindingFlags.Instance | BindingFlags.Public,
+ [
+ typeof(ApplicationContext),
+ typeof(IEnumerable)
+ ]
+ );
+
+ // prepare parameters for the method
+ var parameters = new object[]
+ {
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ };
+
+ // test execution
+ // invoke the method using reflection
+ var preferences = (IEnumerable)getFragmentsMethod.MakeGenericMethod(fragmentType, sectionType)
+ .Invoke(componentHub.FragmentManager, parameters);
+ var castPreferences = Enumerable.Cast(preferences);
+
+ var html = castPreferences.Select(x => x.Render(renderContext, visualTree));
+
+ Assert.Equal(count, html.Count());
+ AssertExtensions.EqualWithPlaceholders(expected, string.Join("", html).Trim());
+ }
+
+ ///
+ /// Test the render function of the fragment manager.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(SectionContentPrimary), typeof(TestPageA), @"")]
+ [InlineData(typeof(TestApplication), typeof(SectionContentPrimary), typeof(IScopeGeneral), null)]
+ [InlineData(typeof(TestApplication), typeof(SectionContentPrimary), typeof(IScope), null)]
+ 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]);
+ var visualTree = new VisualTreeControl(componentHub, renderContext.PageContext);
+
+ // test execution
+ var html = componentHub.FragmentManager.Render(renderContext, visualTree, sectionType);
+
+ Assert.NotNull(html);
+ AssertExtensions.EqualWithPlaceholders(expected, html.FirstOrDefault()?.ToString());
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp.Test/WebPage/UnitTestPageManager.cs b/src/WebExpress.WebApp.Test/WebPage/UnitTestPageManager.cs
new file mode 100644
index 0000000..876485a
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebPage/UnitTestPageManager.cs
@@ -0,0 +1,60 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebCore.WebSitemap;
+
+namespace WebExpress.WebApp.Test.WebPage
+{
+ ///
+ /// Test the page manager.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestPageManager
+ {
+ ///
+ /// Test the id property of the page manager.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(TestPageA), "webexpress.webapp.test.testpagea")]
+ 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()));
+ }
+
+ ///
+ /// Test the process function of the page manager.
+ ///
+ [Theory]
+ [InlineData("http://localhost:8080/server/app/pagea", "webexpress.webapp.test.testpagea")]
+ 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.WebApp.Test/WebTheme/UnitTestThemeManager.cs b/src/WebExpress.WebApp.Test/WebTheme/UnitTestThemeManager.cs
new file mode 100644
index 0000000..97a44d3
--- /dev/null
+++ b/src/WebExpress.WebApp.Test/WebTheme/UnitTestThemeManager.cs
@@ -0,0 +1,54 @@
+using WebExpress.WebApp.Test.Fixture;
+using WebExpress.WebApp.WebTheme;
+
+namespace WebExpress.WebApp.Test.WebTheme
+{
+ ///
+ /// Test the theme manager.
+ ///
+ [Collection("NonParallelTests")]
+ public class UnitTestThemeManager
+ {
+ ///
+ /// Test the id property of the theme.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(TestThemeA), "webexpress.webapp.test.testthemea")]
+ public void Id(Type applicationType, Type themeType, string id)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault();
+
+ // test execution
+ var themeContexts = componentHub.ThemeManager.GetThemes(application, themeType);
+
+ if (id == null)
+ {
+ Assert.Empty(themeContexts);
+ return;
+ }
+
+ Assert.Contains(id, themeContexts.Select(x => x.ThemeId?.ToString()));
+ }
+
+ ///
+ /// Test the GetWebAppTheme function of the theme manager.
+ ///
+ [Theory]
+ [InlineData(typeof(TestApplication), typeof(TestThemeA), "webexpress.webapp.test.testthemea")]
+ public void GetWebAppTheme(Type applicationType, Type themeType, string id)
+ {
+ // preconditions
+ var componentHub = UnitTestControlFixture.CreateAndRegisterComponentHubMock();
+ var application = componentHub.ApplicationManager.GetApplications(applicationType).FirstOrDefault();
+
+ // test execution
+ var themeContext = componentHub.ThemeManager.GetThemes(application, themeType).FirstOrDefault();
+ var theme = componentHub.ThemeManager.GetWebAppTheme(themeContext);
+
+ Assert.NotNull(theme);
+ Assert.Equal(id, theme.GetType().FullName.ToLower());
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/Assets/css/webexpress.webapp.css b/src/WebExpress.WebApp/Assets/css/webexpress.webapp.css
index 44112f8..bd2b678 100644
--- a/src/WebExpress.WebApp/Assets/css/webexpress.webapp.css
+++ b/src/WebExpress.WebApp/Assets/css/webexpress.webapp.css
@@ -1,9 +1,22 @@
-.sidebar {
+body {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+main {
+ flex: auto;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+}
+
+.wx-sidebar {
overflow: auto;
min-height: 100%;
}
-.proterty {
+.wx-proterty {
overflow: auto;
display: block;
background: #C6E2FF;
@@ -11,12 +24,12 @@
min-width: 15%;
}
-.content {
- min-height: 100%;
- display: grid;
- grid-template-columns: auto;
- /*grid-template-rows: 1em auto;*/
+.wx-content {
+ flex: auto;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
}
-.footer {
+.wx-footer {
}
diff --git a/src/WebExpress.WebApp/Assets/css/webexpress.webapp.theme.css b/src/WebExpress.WebApp/Assets/css/webexpress.webapp.theme.css
new file mode 100644
index 0000000..4034cc9
--- /dev/null
+++ b/src/WebExpress.WebApp/Assets/css/webexpress.webapp.theme.css
@@ -0,0 +1,75 @@
+#wx-header {
+ background: var(--bs-dark);
+}
+
+#wx-header-apptitle {
+ color: var(--bs-white);
+}
+
+#wx-header-appnavigation {
+ color: var(--bs-white);
+}
+
+#wx-header-appnavigation .nav-link {
+ color: var(--bs-white);
+}
+
+#wx-header-appnavigation .active {
+ color: var(--bs-info);
+}
+
+#wx-breadcrumb {
+ background: var(--bs-light);
+}
+
+#wx-prologue {
+ background: var(--bs-light);
+}
+
+#wx-searchoptions {
+ background: var(--bs-light);
+}
+
+#wx-sidebar {
+ background: var(--bs-light);
+}
+
+#wx-settingtab {
+ background: var(--bs-light);
+}
+
+#wx-settingmenu {
+ background: var(--bs-light);
+}
+
+#wx-split-gutter {
+ background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important;
+}
+
+#wx-content {
+}
+
+#wx-content-toolbar {
+}
+
+#wx-content-toolbar-more {
+}
+
+#wx-content-main {
+}
+
+#wx-content-main-headline {
+ background: var(--bs-white);
+}
+
+#wx-content-main-headline-more {
+ background: var(--bs-white);
+}
+
+#wx-content-main-property {
+ background: var(--bs-blue200);
+}
+
+#wx-footer {
+ background: var(--bs-light);
+}
\ No newline at end of file
diff --git a/src/WebExpress.WebApp/Assets/js/webexpress.webapp.table.js b/src/WebExpress.WebApp/Assets/js/webexpress.webapp.table.js
index e0677ea..fca7d1c 100644
--- a/src/WebExpress.WebApp/Assets/js/webexpress.webapp.table.js
+++ b/src/WebExpress.WebApp/Assets/js/webexpress.webapp.table.js
@@ -38,7 +38,7 @@ webexpress.webapp.tableCtrl = class extends webexpress.webui.tableCtrl {
receiveData() {
if (this._filter === undefined || this._filter == null) { this._filter = ""; }
if (this._page === undefined || this._page == null) { this._page = 0; }
- $.ajax({ type: "GET", url: this._restUri + "?wql=" + this._filter + "&page=" + this._page, dataType: 'json', }).then(function (response) {
+ $.ajax({ type: "GET", url: this._restUri + "?search=" + this._filter + "&page=" + this._page, dataType: 'json', }).then(function (response) {
var data = response.data;
this.clear();
this.addRange(data);
diff --git a/src/WebExpress.WebApp/Internationalization/de b/src/WebExpress.WebApp/Internationalization/de
index 683b71c..91bf835 100644
--- a/src/WebExpress.WebApp/Internationalization/de
+++ b/src/WebExpress.WebApp/Internationalization/de
@@ -16,14 +16,13 @@ header.setting.label=Einstellungen
header.setting.systeminformation.label=System Informationen
headline.more.title=Weitere Optionen
+toolbar.more.title=Weitere Optionen
status.400.title=Fehlerhafte Anfrage
status.404.title=Ressource nicht gefunden
status.404.description=Der HTTP-Statuscode 404 bedeutet, dass die aufgerufene Ressource auf dem Webserver nicht zu finden ist. Entweder wurden Inhalte der Webseite entfernt oder auf eine andere URL verlegt. Folgende Ursachen können hierfür verantwortlich sein: Die URL ist fehlerhaft angelegt oder falsch intern verlinkt. Die URL wurde falsch eingegeben. Der Webserver ist nicht in Betrieb. Die URL oder die Inhalte wurden gelöscht oder ausgelagert.
status.500.title=Interner Serverfehler
-notificationmanager.initialization=Der Benachrichtigungsmanager wurde initialisiert.
-
pagesettingmanager.initialization=Der Einstellungsseitenmanager wurde initialisiert.
pagesettingmanager.register=Eine Einsteuungsseite wurde dem Einstellungsseitenmanager hinzugefügt.
pagesettingmanager.idless=Eine Einstellungsseite aus dem Plugin '{0}' verfügt über keine Id.
@@ -67,10 +66,13 @@ setting.systeminformation.reboot.label=Neustart
setting.systeminformation.reboot.header=Neustart
setting.systeminformation.reboot.description=Starten Sie den Server neu. Achtung! Der Server ist in der Zeit nicht erreichbar und kann keine Anfragen entgegennehmen.
-setting.tab.general.label=Allgemein
+setting.category.general.name=Allgemeine Einstellungen
+setting.category.general.description=Allgemeine Einstellungen für die Webanwendung.
+setting.group.general.name=Allgemein
+setting.group.general.description=Allgemeine Einstellungen für die Webanwendung.
+setting.tab.general.label=Allgemein
setting.group.system.label=System
-
setting.titel.plugin.label=Plugins
setting.titel.systeminformation.label=Systeminformationen
setting.titel.log.label=Log
diff --git a/src/WebExpress.WebApp/Internationalization/en b/src/WebExpress.WebApp/Internationalization/en
index f768920..f37ce86 100644
--- a/src/WebExpress.WebApp/Internationalization/en
+++ b/src/WebExpress.WebApp/Internationalization/en
@@ -16,14 +16,13 @@ header.setting.label=Settings
header.setting.systeminformation.label=System information
headline.more.title=More options
+toolbar.more.title=More options
status.400.title=Bad Request
status.404.title=Resource not found
status.404.description=The HTTP status code 404 means that the called resource cannot be found on the Web server. Either content has been removed or moved to a different URL. The following causes may be responsible for this: The URL is created incorrectly or incorrectly linked internally. The URL was entered incorrectly. The web server is not in operation. The URL or content has been deleted or paged out.
status.500.title=Internal Server Error
-notificationmanager.initialization=The notification manager has been initialized.
-
pagesettingmanager.initialization=The settings page manager has been initialized.
pagesettingmanager.register=A settings page has been added to the settings page manager.
pagesettingmanager.idless=A settings page from the plugin '{0}' does not have an id.
@@ -82,10 +81,13 @@ setting.logfile.switchon.header=Enable logging
setting.logfile.switchon.description=Activation is only valid until the next restart. To enable it permanently, change the settings in the configuration file.
setting.logfile.switchon.success=Logging has been enabled.
-setting.tab.general.label=General
+setting.category.general.name=General settings
+setting.category.general.description=General settings for the web application.
+setting.group.general.name=General
+setting.group.general.description=General settings for the web application.
+setting.tab.general.label=General
setting.group.system.label=System
-
setting.titel.plugin.label=Plugins
setting.titel.systeminformation.label=System information
setting.titel.log.label=Log
diff --git a/src/WebExpress.WebApp/Model/WebItem.cs b/src/WebExpress.WebApp/Model/WebItem.cs
deleted file mode 100644
index 56d1e11..0000000
--- a/src/WebExpress.WebApp/Model/WebItem.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Text.Json.Serialization;
-using WebExpress.WebIndex;
-using WebExpress.WebIndex.WebAttribute;
-
-namespace WebExpress.WebApp.Model
-{
- public class WebItem : IIndexItem
- {
- ///
- /// Returns or sets the id.
- ///
- [JsonPropertyName("id")]
- [IndexIgnore]
- public Guid Id { get; set; } = Guid.NewGuid();
-
- ///
- /// Returns or sets the name.
- ///
- [JsonPropertyName("name")]
- [IndexIgnore]
- public virtual string Name { get; set; }
-
- ///
- /// Returns or sets the uri of the web item.
- ///
- [JsonPropertyName("uri")]
- public virtual string Uri { get; set; }
-
- ///
- /// Returns or sets the label of the web item.
- ///
- [JsonPropertyName("label")]
- public virtual string Label { get; set; }
-
- ///
- /// Constructor
- ///
- public WebItem()
- {
- }
-
- ///
- /// Copy-Constructor
- /// Creates a deep copy.
- ///
- /// The web item to be copied.
- public WebItem(WebItem item)
- {
- Id = item.Id;
- Name = item.Name;
- Uri = item.Uri;
- Label = item.Label;
- }
-
- ///
- /// Conversion to string.
- ///
- /// The object in its string representation.
- public override string ToString()
- {
- return $"{Label} ({Id})";
- }
- }
-}
diff --git a/src/WebExpress.WebApp/Model/WebItemGroup.cs b/src/WebExpress.WebApp/Model/WebItemGroup.cs
deleted file mode 100644
index 0b571cd..0000000
--- a/src/WebExpress.WebApp/Model/WebItemGroup.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace WebExpress.WebApp.Model
-{
- public class WebItemGroup : WebItem
- {
-
- }
-}
diff --git a/src/WebExpress.WebApp/Model/WebItemUser.cs b/src/WebExpress.WebApp/Model/WebItemUser.cs
deleted file mode 100644
index 8dd90b5..0000000
--- a/src/WebExpress.WebApp/Model/WebItemUser.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Collections.Generic;
-
-namespace WebExpress.WebApp.Model
-{
- ///
- /// Represents a user in the web item context.
- ///
- public class WebItemUser : WebItem
- {
- ///
- /// Returns the label of the object.
- ///
- public override string Label => !string.IsNullOrWhiteSpace(Firstname) ? $"{Lastname}, {Firstname}" : Lastname;
-
- ///
- /// Returns the name of the object.
- ///
- public override string Name => Label;
-
- ///
- /// Returns or sets the login name.
- ///
- public string Login { get; set; }
-
- ///
- /// Returns or sets the first name.
- ///
- public string Firstname { get; set; }
-
- ///
- /// Returns or sets the last name.
- ///
- public string Lastname { get; set; }
-
- ///
- /// Returns or sets the email address.
- ///
- public string Email { get; set; }
-
- ///
- /// Returns or sets the groups.
- ///
- public IEnumerable Groups { get; set; }
- }
-}
diff --git a/src/WebExpress.WebApp/Module.cs b/src/WebExpress.WebApp/Module.cs
deleted file mode 100644
index 282080a..0000000
--- a/src/WebExpress.WebApp/Module.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using WebExpress.WebCore.WebAttribute;
-using WebExpress.WebCore.WebModule;
-
-namespace WebExpress.WebApp
-{
- [Application("*")]
- [Name("module.name")]
- [Description("module.description")]
- [Icon("/assets/img/Logo.png")]
- [AssetPath("/")]
- [ContextPath("/modules/wxapp")]
- public sealed class Module : IModule
- {
- ///
- /// Constructor
- ///
- 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)
- {
-
- }
-
- ///
- /// Invoked when the module starts working. The call is concurrent.
- ///
- public void Run()
- {
-
- }
-
- ///
- /// Release unmanaged resources that have been reserved during use.
- ///
- public void Dispose()
- {
-
- }
- }
-}
diff --git a/src/WebExpress.WebApp/Plugin.cs b/src/WebExpress.WebApp/Plugin.cs
deleted file mode 100644
index fca2ddf..0000000
--- a/src/WebExpress.WebApp/Plugin.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System.Collections.Generic;
-using WebExpress.WebCore.WebAttribute;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebJob;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebCore.WebPlugin;
-using WebExpress.WebCore.WebResource;
-using WebExpress.WebApp.WebJob;
-using WebExpress.WebApp.WebScope;
-using WebExpress.WebUI.WebSettingPage;
-
-[assembly: SystemPlugin()]
-
-namespace WebExpress.WebApp
-{
- [Name("WebExpress.WebApp")]
- [Description("plugin.description")]
- [Icon("/assets/img/Logo.png")]
- [Dependency("webexpress.webui")]
- public sealed class Plugin : IPlugin
- {
- ///
- /// Constructor
- ///
- public Plugin()
- {
- ComponentManager.ResourceManager.AddResource += AddResource;
- }
-
- ///
- /// 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)
- {
- ComponentManager.JobManager.Register(context, new Cron(context.Host, "30", "0", "1", "*", "*"));
- }
-
- ///
- /// Called when the plugin starts working. Run is called concurrently.
- ///
- public void Run()
- {
- }
-
- ///
- /// Release of unmanaged resources reserved during use.
- ///
- public void Dispose()
- {
- ComponentManager.ResourceManager.AddResource -= AddResource;
- }
-
- ///
- /// Manipulates the new resources by adding the default scops.
- ///
- /// The trigger of the event.
- /// The resource context.
- private void AddResource(object sender, IResourceContext resourceContext)
- {
- if (resourceContext?.Scopes is List scopes)
- {
- var scopeGeneral = typeof(ScopeGeneral).FullName.ToString().ToLower();
- var scopeSetting = typeof(ScopeSetting).FullName.ToString().ToLower();
-
- if (resourceContext is IPage && !scopes.Contains(scopeGeneral))
- {
- scopes.Add(scopeGeneral);
- }
-
- if (resourceContext is IPageSetting && !scopes.Contains(scopeSetting))
- {
- scopes.Add(scopeSetting);
- }
- }
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WWW/Api/1/RestPopupNotification.cs b/src/WebExpress.WebApp/WWW/Api/1/RestPopupNotification.cs
new file mode 100644
index 0000000..6fd18f3
--- /dev/null
+++ b/src/WebExpress.WebApp/WWW/Api/1/RestPopupNotification.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Linq;
+using WebExpress.WebCore.WebApplication;
+using WebExpress.WebCore.WebAttribute;
+using WebExpress.WebCore.WebComponent;
+using WebExpress.WebCore.WebMessage;
+using WebExpress.WebCore.WebRestApi;
+using WebExpress.WebUI.WebNotification;
+
+namespace WebExpress.WebApp.WWW.Api._1
+{
+ ///
+ /// Returns the status and progress of a task (WebTask).
+ ///
+ [Method(CrudMethod.GET)]
+ [Method(CrudMethod.DELETE)]
+ [IncludeSubPaths(true)]
+ public sealed class RestPopupNotification : IRestApi
+ {
+ private readonly IComponentHub _componentHub;
+ private readonly IApplicationContext _applicationContext;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RestPopupNotification(IComponentHub componentHub, IApplicationContext applicationContext)
+ {
+ _componentHub = componentHub;
+ _applicationContext = applicationContext;
+ }
+
+ ///
+ /// Creates data based on the provided request.
+ ///
+ /// The request containing the data to create.
+ public void CreateData(Request request)
+ {
+ }
+
+ ///
+ /// Retrieves data based on the provided request.
+ ///
+ /// The request containing the criteria for data retrieval.
+ /// A collection of notifications.
+ public object GetData(Request request)
+ {
+
+ return _componentHub.GetComponentManager()?.GetNotifications(_applicationContext, request);
+ }
+
+ ///
+ /// Updates data based on the provided request.
+ ///
+ /// The request containing the data to update.
+ public void UpdateData(Request request)
+ {
+ }
+
+ ///
+ /// Deletes data based on the provided request.
+ ///
+ /// The request containing the data to delete.
+ public void DeleteData(Request request)
+ {
+ if (Guid.TryParse(request.Uri.PathSegments.Last()?.ToString(), out Guid id))
+ {
+ _componentHub.GetComponentManager()?.RemoveNotifications(id);
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WWW/Api/1/RestTaskStatus.cs b/src/WebExpress.WebApp/WWW/Api/1/RestTaskStatus.cs
new file mode 100644
index 0000000..ddc5b6c
--- /dev/null
+++ b/src/WebExpress.WebApp/WWW/Api/1/RestTaskStatus.cs
@@ -0,0 +1,72 @@
+//using System.Collections;
+//using System.Linq;
+//using WebExpress.WebCore.WebAttribute;
+//using WebExpress.WebCore.WebComponent;
+//using WebExpress.WebCore.WebMessage;
+//using WebExpress.WebCore.WebResource;
+
+//namespace WebExpress.WebApp.WWW.Api.V1
+//{
+// ///
+// /// Determines the status and progress of a task (WebTask).
+// ///
+// [Segment("taskstatus", "")]
+// [ContextPath("/api/v1")]
+// [IncludeSubPaths(true)]
+// [Module]
+// [Optional]
+// public sealed class RestTaskStatus : ResourceRest
+// {
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// public RestTaskStatus()
+// {
+// }
+
+// ///
+// /// Initialization
+// ///
+// /// The context.
+// public override void Initialization(IResourceContext context)
+// {
+// base.Initialization(context);
+// }
+
+// ///
+// /// Processing of the resource.
+// ///
+// /// The request.
+// /// An enumeration that can be serialized using the JsonSerializer.
+// public override ICollection GetData(Request request)
+// {
+// var id = request.Uri.PathSegments.Last().Value;
+
+// if (ComponentManager.TaskManager.ContainsTask(id))
+// {
+// var task = ComponentManager.TaskManager.GetTask(id);
+
+// return new object[]
+// {
+// new
+// {
+// Id = id,
+// task.State,
+// task.Progress,
+// task.Message
+// }
+// };
+// }
+
+// return new object[]
+// {
+// new
+// {
+// Id = id,
+// State = default(string),
+// Progress = 0
+// }
+// };
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebResource/ResourceRestCrud.cs b/src/WebExpress.WebApp/WebApi/RestApiCrud.cs
similarity index 62%
rename from src/WebExpress.WebApp/WebResource/ResourceRestCrud.cs
rename to src/WebExpress.WebApp/WebApi/RestApiCrud.cs
index e857f89..5a5deb7 100644
--- a/src/WebExpress.WebApp/WebResource/ResourceRestCrud.cs
+++ b/src/WebExpress.WebApp/WebApi/RestApiCrud.cs
@@ -1,85 +1,118 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebMessage;
-using WebExpress.WebCore.WebResource;
-using WebExpress.WebIndex;
-using WebExpress.WebIndex.WebAttribute;
-using WebExpress.WebIndex.Wql;
-
-namespace WebExpress.WebApp.WebResource
-{
- public abstract class ResourceRestCrud : ResourceRest where T : IIndexItem
- {
- ///
- /// Returns the lock object.
- ///
- protected object Guard { get; } = new object();
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The request.
- /// An enumeration of which json serializer can be serialized.
- public abstract IEnumerable GetColumns(Request request);
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The filtering and sorting options.
- /// The request.
- /// An enumeration of which json serializer can be serialized.
- public abstract IEnumerable GetData(IWqlStatement wql, Request request);
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The request.
- /// An enumeration of which json serializer can be serialized.
- public override object GetData(Request request)
- {
- var itemCount = 50;
- var search = request.HasParameter("search") ? request.GetParameter("search").Value : string.Empty;
- var wql = request.HasParameter("wql") ? request.GetParameter("wql").Value : null;
- var page = request.GetParameter("page");
- var columns = request.HasParameter("columns");
- var pagenumber = !string.IsNullOrWhiteSpace(page?.Value) ? Convert.ToInt32(page?.Value) : 0;
-
- if (columns)
- {
- return new { Columns = GetColumns(request) };
- }
-
- lock (Guard)
- {
- var wqlStatement = ComponentManager.GetComponent().Retrieve(wql ?? $"{GetDefaultSearchAttribute()}='{search}'");
- var data = GetData(wqlStatement, request);
-
- var count = data.Count();
- var totalpage = Math.Round(count / (double)itemCount, MidpointRounding.ToEven);
-
- if (page == null)
- {
- return new { Data = data };
- }
-
- return new { data = data.Skip(itemCount * pagenumber).Take(itemCount), pagination = new { pagenumber = pagenumber, totalpage = totalpage } };
- }
- }
-
- ///
- /// Returns the attribute name that has been set as for search queries.
- ///
- /// The name of the default attribute.
- protected virtual string GetDefaultSearchAttribute()
- {
- return typeof(T).GetProperties()
- //.Where(x => x.GetCustomAttribute() != null)
- .Where(x => x.GetCustomAttribute() == null)
- .Select(x => x.Name)
- .FirstOrDefault();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.WebMessage;
+using WebExpress.WebCore.WebRestApi;
+using WebExpress.WebIndex;
+using WebExpress.WebIndex.WebAttribute;
+using WebExpress.WebIndex.Wql;
+
+namespace WebExpress.WebApp.WebApi
+{
+
+ ///
+ /// Abstract class providing CRUD operations for REST API.
+ ///
+ /// Type of the index item.
+ public abstract class RestApiCrud : IRestApi where T : IIndexItem
+ {
+ ///
+ /// Returns the lock object.
+ ///
+ protected object Guard { get; } = new object();
+
+ ///
+ /// Processing of the resource that was called via the get request.
+ ///
+ /// The request.
+ /// An enumeration of which json serializer can be serialized.
+ public abstract IEnumerable GetColumns(Request request);
+
+ ///
+ /// Processing of the resource that was called via the get request.
+ ///
+ /// The filtering and sorting options.
+ /// The request.
+ /// An enumeration of which json serializer can be serialized.
+ public abstract IEnumerable GetData(IWqlStatement wql, Request request);
+
+ ///
+ /// Processing of the resource that was called via the get request.
+ ///
+ /// The request.
+ /// An enumeration of which json serializer can be serialized.
+ public virtual object GetData(Request request)
+ {
+ var itemCount = 50;
+ var search = request.HasParameter("search") ? request.GetParameter("search").Value : string.Empty;
+ var wql = request.HasParameter("wql") ? request.GetParameter("wql").Value : null;
+ var page = request.GetParameter("page");
+ var columns = request.HasParameter("columns");
+ var pagenumber = !string.IsNullOrWhiteSpace(page?.Value) ? Convert.ToInt32(page?.Value) : 0;
+
+ if (columns)
+ {
+ return new { Columns = GetColumns(request) };
+ }
+
+ lock (Guard)
+ {
+ var wqlStatement = !string.IsNullOrWhiteSpace(search) || !string.IsNullOrWhiteSpace(wql)
+ ? WebEx.ComponentHub.GetComponentManager()?.Retrieve(wql ?? $"{GetDefaultSearchAttribute()}='{search}*'")
+ : WebEx.ComponentHub.GetComponentManager()?.Retrieve("");
+ var data = GetData(wqlStatement, request);
+
+ var count = data.Count();
+ var totalpage = Math.Round(count / (double)itemCount, MidpointRounding.ToEven);
+
+ if (page == null)
+ {
+ return new { Data = data };
+ }
+
+ return new { data = data.Skip(itemCount * pagenumber).Take(itemCount), pagination = new { pagenumber, totalpage } };
+ }
+ }
+
+ ///
+ /// Creates data.
+ ///
+ /// The request.
+ public void CreateData(Request request)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Updates data.
+ ///
+ /// The request.
+ public void UpdateData(Request request)
+ {
+ }
+ ///
+ /// Deletes data.
+ ///
+ /// The id of the data to delete.
+ /// The request.
+ public void DeleteData(Request request)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Returns the attribute name that has been set as for search queries.
+ ///
+ /// The name of the default attribute.
+ protected virtual string GetDefaultSearchAttribute()
+ {
+ return typeof(T).GetProperties()
+ .Where(x => x.GetCustomAttribute() != null)
+ .Where(x => x.GetCustomAttribute() == null)
+ .Select(x => x.Name)
+ .FirstOrDefault();
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebResource/ResourceRestCrudColumn.cs b/src/WebExpress.WebApp/WebApi/RestApiCrudColumn.cs
similarity index 64%
rename from src/WebExpress.WebApp/WebResource/ResourceRestCrudColumn.cs
rename to src/WebExpress.WebApp/WebApi/RestApiCrudColumn.cs
index 4549d58..7509327 100644
--- a/src/WebExpress.WebApp/WebResource/ResourceRestCrudColumn.cs
+++ b/src/WebExpress.WebApp/WebApi/RestApiCrudColumn.cs
@@ -1,11 +1,11 @@
using System.Text.Json.Serialization;
-namespace WebExpress.WebApp.WebResource
+namespace WebExpress.WebApp.WebApi
{
///
- /// Metainformationen einer CRUD-Tabellensplate
+ /// Represents a column in a REST CRUD resource.
///
- public class ResourceRestCrudColumn
+ public class RestApiCrudColumn
{
///
/// Returns or sets the label. der Splalte
@@ -14,28 +14,28 @@ public class ResourceRestCrudColumn
public string Label { get; set; }
///
- /// Returns or sets the icon. der Spalte oder null
+ /// Returns or sets the icon.
///
[JsonPropertyName("icon")]
public string Icon { get; set; }
///
- /// Returns or sets the width. der Tabellenspalte in %, null für auto
+ /// Returns or sets the width of the table column in percentage, null for auto.
///
[JsonPropertyName("width")]
public uint? Width { get; set; }
///
- /// Liefert oder setzt den Javascriptcode, welche die Daten der Zelle rendert
+ /// Returns or sets the Javascript code that renders the data of the cell.
///
[JsonPropertyName("render")]
public string Render { get; set; }
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The label of the column.
- public ResourceRestCrudColumn(string label)
+ public RestApiCrudColumn(string label)
{
Label = label;
}
diff --git a/src/WebExpress.WebApp/WebApi/V1/RestPopupNotification.cs b/src/WebExpress.WebApp/WebApi/V1/RestPopupNotification.cs
deleted file mode 100644
index fa3f8b8..0000000
--- a/src/WebExpress.WebApp/WebApi/V1/RestPopupNotification.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Collections;
-using WebExpress.WebCore.WebAttribute;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebMessage;
-using WebExpress.WebCore.WebResource;
-using WebExpress.WebApp.WebNotificaation;
-
-namespace WebExpress.WebApp.WebAPI.V1
-{
- ///
- /// Returns the status and progress of a task (WebTask).
- ///
- [Segment("popupnotifications", "")]
- [ContextPath("/api/v1")]
- [Module]
- [IncludeSubPaths(true)]
- [Optional]
- public sealed class RestPopupNotification : ResourceRest
- {
- ///
- /// Constructor
- ///
- public RestPopupNotification()
- {
- }
-
- ///
- /// Initialization
- ///
- /// The context.
- public override void Initialization(IResourceContext context)
- {
- base.Initialization(context);
- }
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The request.
- /// An enumeration that can be serialized using the JsonSerializer.
- public override ICollection GetData(Request request)
- {
- return (ICollection)ComponentManager.GetComponent()?.GetNotifications(request);
- }
-
- ///
- /// Processing of the resource that was called via the delete request.
- ///
- /// The id to delete.
- /// The request.
- /// The result of the deletion.
- public override bool DeleteData(string id, Request request)
- {
- ComponentManager.GetComponent()?.RemoveNotification(request, id);
-
- return true;
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebApi/V1/RestTaskStatus.cs b/src/WebExpress.WebApp/WebApi/V1/RestTaskStatus.cs
deleted file mode 100644
index aa0ed08..0000000
--- a/src/WebExpress.WebApp/WebApi/V1/RestTaskStatus.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System.Collections;
-using System.Linq;
-using WebExpress.WebCore.WebAttribute;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebMessage;
-using WebExpress.WebCore.WebResource;
-
-namespace WebExpress.WebApp.WebAPI.V1
-{
- ///
- /// Determines the status and progress of a task (WebTask).
- ///
- [Segment("taskstatus", "")]
- [ContextPath("/api/v1")]
- [IncludeSubPaths(true)]
- [Module]
- [Optional]
- public sealed class RestTaskStatus : ResourceRest
- {
- ///
- /// Constructor
- ///
- public RestTaskStatus()
- {
- }
-
- ///
- /// Initialization
- ///
- /// The context.
- public override void Initialization(IResourceContext context)
- {
- base.Initialization(context);
- }
-
- ///
- /// Processing of the resource.
- ///
- /// The request.
- /// An enumeration that can be serialized using the JsonSerializer.
- public override ICollection GetData(Request request)
- {
- var id = request.Uri.PathSegments.Last().Value;
-
- if (ComponentManager.TaskManager.ContainsTask(id))
- {
- var task = ComponentManager.TaskManager.GetTask(id);
-
- return new object[]
- {
- new
- {
- Id = id,
- task.State,
- task.Progress,
- task.Message
- }
- };
- }
-
- return new object[]
- {
- new
- {
- Id = id,
- State = default(string),
- Progress = 0
- }
- };
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebApi/V1/RestUserManagement.cs b/src/WebExpress.WebApp/WebApi/V1/RestUserManagement.cs
deleted file mode 100644
index edda088..0000000
--- a/src/WebExpress.WebApp/WebApi/V1/RestUserManagement.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using WebExpress.WebCore.WebAttribute;
-using WebExpress.WebCore.WebMessage;
-using WebExpress.WebCore.WebResource;
-using WebExpress.WebApp.Model;
-using WebExpress.WebApp.WebResource;
-using WebExpress.WebIndex.Wql;
-using WebExpress.WebUI;
-using static WebExpress.WebCore.Internationalization.InternationalizationManager;
-
-namespace WebExpress.WebAPI.V1
-{
- ///
- /// REST API for user management.
- ///
- [Segment("user", "")]
- [ContextPath("/api/v1")]
- [Module]
- [Optional]
- public sealed class RestUserManagement : ResourceRestCrud
- {
- ///
- /// Constructor
- ///
- public RestUserManagement()
- {
- }
-
- ///
- /// Initialization
- ///
- /// The context.
- public override void Initialization(IResourceContext context)
- {
- base.Initialization(context);
- }
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The request.
- /// An enumeration of which json serializer can be serialized.
- public override IEnumerable GetColumns(Request request)
- {
- return new ResourceRestCrudColumn[]
- {
- new ResourceRestCrudColumn(I18N(request, "webexpress.webapp:setting.usermanager.user.login.label"))
- {
- Render = "return item.Login;",
- Width = 5
- },
- new ResourceRestCrudColumn(I18N(request, "webexpress.webapp:setting.usermanager.user.name.label"))
- {
- Render = "return item.Lastname + ', ' + item.Firstname;"
- },
- new ResourceRestCrudColumn(I18N(request, "webexpress.webapp:setting.usermanager.user.groups.label"))
- {
- Render = "var html = '' + item.Groups.map(function(group) { return '' + group.Name + ' '; }).join('') + ' '; return html;"
- },
- new ResourceRestCrudColumn(I18N(request, "webexpress.webapp:setting.usermanager.user.email.label"))
- {
- Render = "return item.Email;"
- }
- };
- }
-
- ///
- /// Processing of the resource that was called via the get request.
- ///
- /// The filtering and sorting options.
- /// The request.
- /// An enumeration of which json serializer can be serialized.
- public override IEnumerable GetData(IWqlStatement wql, Request request)
- {
- var users = wql.Apply();
-
- return users.Select(x => new WebItemUser()
- {
- Id = x.Id,
- Login = x.Login,
- Firstname = x.Firstname,
- Lastname = x.Lastname,
- Email = x.Email,
- Groups = x.Groups.Select(y => new WebItemGroup() { Id = y.Id, Name = y.Name })
- });
- }
-
- ///
- /// Processing of the resource that was called via the delete request.
- ///
- /// The id to delete.
- /// The request.
- /// The result of the deletion.
- public override bool DeleteData(string id, Request request)
- {
- return true;
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiFormItemInputSelection.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiFormItemInputSelection.cs
new file mode 100644
index 0000000..d7079dc
--- /dev/null
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiFormItemInputSelection.cs
@@ -0,0 +1,67 @@
+//using System.Linq;
+//using System.Text;
+//using System.Text.Json;
+//using WebExpress.WebUI.WebControl;
+
+//namespace WebExpress.WebApp.WebApiControl;
+
+//public class ControlApiFormItemInputSelection : ControlFormItemInputSelection, IControlApi
+//{
+// ///
+// /// Returns or sets the uri that determines the options.
+// ///
+// public string RestUri { get; set; }
+
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlApiFormItemInputSelection(string id = null)
+// : base(id)
+// {
+// }
+
+// ///
+// /// 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 override string GetScript(RenderContextForm context, string id, string css)
+// {
+// var settings = new
+// {
+// id = id,
+// name = Name,
+// css = css,
+// placeholder = Placeholder,
+// hidedescription = HideDescription,
+// multiSelect = MultiSelect,
+// optionuri = RestUri?.ToString()
+// };
+
+// var jsonOptions = new JsonSerializerOptions { WriteIndented = false };
+// var settingsJson = JsonSerializer.Serialize(settings, jsonOptions);
+// var optionsJson = JsonSerializer.Serialize(Options, jsonOptions);
+// var builder = new StringBuilder();
+
+// builder.AppendLine($"$(document).ready(function () {{");
+// builder.AppendLine($"let settings = {settingsJson};");
+// builder.AppendLine($"var options = {optionsJson};");
+// builder.AppendLine($"let container = $('#{id}');");
+// builder.AppendLine($"let obj = new webexpress.webapp.selectionCtrl(settings);");
+// builder.AppendLine($"obj.options = options;");
+// builder.AppendLine($"obj.receiveData();");
+// builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];");
+// builder.AppendLine($"obj.on('webexpress.webui.change.filter', function(key) {{ obj.receiveData(key); }});");
+// if (OnChange != null)
+// {
+// builder.AppendLine($"obj.on('webexpress.webui.change.value', function() {{ {OnChange} }});");
+// }
+// builder.AppendLine($"container.replaceWith(obj.getCtrl);");
+// builder.AppendLine($"}});");
+
+// return builder.ToString();
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiFormularItemInputSelection.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiFormularItemInputSelection.cs
deleted file mode 100644
index edec937..0000000
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiFormularItemInputSelection.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System.Linq;
-using System.Text;
-using System.Text.Json;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebApiControl;
-
-public class ControlApiFormularItemInputSelection : ControlFormItemInputSelection, IControlApi
-{
- ///
- /// Returns or sets the uri that determines the options.
- ///
- public string RestUri { get; set; }
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlApiFormularItemInputSelection(string id = null)
- : base(id)
- {
- }
-
- ///
- /// 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 override string GetScript(RenderContextFormular context, string id, string css)
- {
- var settings = new
- {
- id = id,
- name = Name,
- css = css,
- placeholder = Placeholder,
- hidedescription = HideDescription,
- multiSelect = MultiSelect,
- optionuri = RestUri?.ToString()
- };
-
- var jsonOptions = new JsonSerializerOptions { WriteIndented = false };
- var settingsJson = JsonSerializer.Serialize(settings, jsonOptions);
- var optionsJson = JsonSerializer.Serialize(Options, jsonOptions);
- var builder = new StringBuilder();
-
- builder.AppendLine($"$(document).ready(function () {{");
- builder.AppendLine($"let settings = {settingsJson};");
- builder.AppendLine($"var options = {optionsJson};");
- builder.AppendLine($"let container = $('#{id}');");
- builder.AppendLine($"let obj = new webexpress.webapp.selectionCtrl(settings);");
- builder.AppendLine($"obj.options = options;");
- builder.AppendLine($"obj.receiveData();");
- builder.AppendLine($"obj.value = [{string.Join(",", Values.Select(x => $"'{x}'"))}];");
- builder.AppendLine($"obj.on('webexpress.webui.change.filter', function(key) {{ obj.receiveData(key); }});");
- if (OnChange != null)
- {
- builder.AppendLine($"obj.on('webexpress.webui.change.value', function() {{ {OnChange} }});");
- }
- builder.AppendLine($"container.replaceWith(obj.getCtrl);");
- builder.AppendLine($"}});");
-
- return builder.ToString();
- }
-}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiModalProgressTaskState.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiModalProgressTaskState.cs
index 75a3243..0355652 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiModalProgressTaskState.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiModalProgressTaskState.cs
@@ -1,67 +1,67 @@
-using System;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
+//using System;
+//using WebExpress.WebCore.WebComponent;
+//using WebExpress.WebCore.WebHtml;
+//using WebExpress.WebCore.WebPage;
+//using WebExpress.WebUI.WebControl;
-namespace WebExpress.WebApp.WebApiControl
-{
- ///
- /// Dialog that contains the progress bar of a web task.
- ///
- public class ControlApiModalProgressTaskState : ControlModal
- {
- ///
- /// Returns or sets the progress bar.
- ///
- private ControlProgressBar ProgressBar { get; set; }
+//namespace WebExpress.WebApp.WebApiControl
+//{
+// ///
+// /// Dialog that contains the progress bar of a web task.
+// ///
+// public class ControlApiModalProgressTaskState : ControlModal
+// {
+// ///
+// /// Returns or sets the progress bar.
+// ///
+// private ControlProgressBar ProgressBar { get; set; }
- ///
- /// Returns or sets the progress message.
- ///
- private ControlText Message { get; set; }
+// ///
+// /// Returns or sets the progress message.
+// ///
+// private ControlText Message { get; set; }
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlApiModalProgressTaskState(string id)
- : base(id ?? Guid.NewGuid().ToString())
- {
- ProgressBar = new ControlProgressBar($"progressbar_{Id}")
- {
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Two),
- Color = new PropertyColorProgress(TypeColorProgress.Primary),
- Format = TypeFormatProgress.Animated
- };
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlApiModalProgressTaskState(string id)
+// : base(id ?? Guid.NewGuid().ToString())
+// {
+// ProgressBar = new ControlProgressBar($"progressbar_{Id}")
+// {
+// Margin = new PropertySpacingMargin(PropertySpacing.Space.Two),
+// Color = new PropertyColorProgress(TypeColorProgress.Primary),
+// Format = TypeFormatProgress.Animated
+// };
- Message = new ControlText($"message_{Id}")
- {
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Two),
- TextColor = new PropertyColorText(TypeColorText.Secondary)
- };
+// Message = new ControlText($"message_{Id}")
+// {
+// Margin = new PropertySpacingMargin(PropertySpacing.Space.Two),
+// TextColor = new PropertyColorText(TypeColorText.Secondary)
+// };
- Fade = false;
- ShowIfCreated = true;
+// Fade = false;
+// ShowIfCreated = true;
- Content.Add(ProgressBar);
- Content.Add(Message);
- }
+// Content.Add(ProgressBar);
+// Content.Add(Message);
+// }
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module));
- var code = $"updateTaskModal('{Id}', '{module?.ContextPath.Append("api/v1/taskstatus")}')";
+// ///
+// /// Convert to html.
+// ///
+// /// The context in which the control is rendered.
+// /// The control as html.
+// public override IHtmlNode Render(RenderContext context)
+// {
+// var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module));
+// var code = $"updateTaskModal('{Id}', '{module?.ContextPath.Append("api/v1/taskstatus")}')";
- context.VisualTree.AddScript("webexpress.webapp:controlapimodalprogresstaskstate", code);
+// context.VisualTree.AddScript("webexpress.webapp:controlapimodalprogresstaskstate", code);
- return base.Render(context);
- }
- }
-}
+// return base.Render(context);
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiNotificationPopup.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiNotificationPopup.cs
index bd8482b..ee13e7a 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiNotificationPopup.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiNotificationPopup.cs
@@ -1,58 +1,64 @@
using System;
using System.Text;
using System.Text.Json;
-using WebExpress.WebCore.WebComponent;
+using WebExpress.WebApp.WWW.Api._1;
+using WebExpress.WebCore;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebApiControl
{
///
- /// Popup-Benachrichtigungen
+ /// Represents a control for displaying notification popups via API.
///
- public class ControlApiNotificationPopup : ControlPanel
+ public class ControlApiNotificationPopup : Control
{
+ private static readonly JsonSerializerOptions _jsonOptions = new() { WriteIndented = false };
+
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
- /// Die Steuerelement-Id
+ /// The optional identifier for the control. If not provided, a new GUID will be generated.
public ControlApiNotificationPopup(string id = null)
: base(id ?? Guid.NewGuid().ToString())
{
- Classes.Add("popupnotification");
}
///
- /// Convert to html.
+ /// Converts the control to an HTML representation.
///
- /// 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 visual tree representing the control's structure.
+ /// An HTML node representing the rendered control.
+ public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree)
{
- var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module));
-
+ var applicationContext = renderContext?.PageContext?.ApplicationContext;
var settings = new
{
id = "26E517F5-56F7-485E-A212-6033618708F3",
- resturi = module?.ContextPath.Append("api/v1/popupnotifications")?.ToString(),
+ resturi = WebEx.ComponentHub.SitemapManager.GetUri(applicationContext).ToString(),
intervall = 15000
};
- var jsonOptions = new JsonSerializerOptions { WriteIndented = false };
- var settingsJson = JsonSerializer.Serialize(settings, jsonOptions);
+ var settingsJson = JsonSerializer.Serialize(settings, _jsonOptions);
var builder = new StringBuilder();
builder.AppendLine($"$(document).ready(function () {{");
builder.AppendLine($"let settings = {settingsJson};");
- builder.AppendLine($"let container = $('#{Id}');");
+ builder.AppendLine($"let container = $('#{settings.id}');");
builder.AppendLine($"let obj = new webexpress.webapp.popupNotificationCtrl(settings);");
builder.AppendLine($"container.replaceWith(obj.getCtrl);");
builder.AppendLine($"}});");
- context.VisualTree.AddScript("webexpress.webapp:controlapinotificationpopup", builder.ToString());
+ visualTree.AddScript("webexpress.webapp:controlapinotificationpopup", builder.ToString());
+
+ var ctrl = new ControlPanel(settings.id)
+ {
+ Classes = ["popupnotification"]
+ };
- return base.Render(context);
+ return ctrl.Render(renderContext, visualTree);
}
}
}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiProgressBarTaskState.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiProgressBarTaskState.cs
index 74058b7..8a1f2ea 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiProgressBarTaskState.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiProgressBarTaskState.cs
@@ -1,44 +1,44 @@
-using System;
-using WebExpress.WebCore.WebComponent;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
+//using System;
+//using WebExpress.WebCore.WebComponent;
+//using WebExpress.WebCore.WebHtml;
+//using WebExpress.WebCore.WebPage;
+//using WebExpress.WebUI.WebControl;
-namespace WebExpress.WebApp.WebApiControl
-{
- ///
- /// Task progress bar.
- ///
- public class ControlApiProgressBarTaskState : ControlProgressBar
- {
- ///
- /// Returns or sets the Java script function, which is called when the task is completed.
- ///
- public string OnFinishScript { get; set; }
+//namespace WebExpress.WebApp.WebApiControl
+//{
+// ///
+// /// Task progress bar.
+// ///
+// public class ControlApiProgressBarTaskState : ControlProgressBar
+// {
+// ///
+// /// Returns or sets the Java script function, which is called when the task is completed.
+// ///
+// public string OnFinishScript { get; set; }
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlApiProgressBarTaskState(string id)
- : base(id ?? Guid.NewGuid().ToString())
- {
- }
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlApiProgressBarTaskState(string id)
+// : base(id ?? Guid.NewGuid().ToString())
+// {
+// }
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module));
- var code = $"updateTaskProgressBar('{Id}', '{module?.ContextPath.Append("api/v1/taskstatus")}', {OnFinishScript});";
+// ///
+// /// Convert to html.
+// ///
+// /// The context in which the control is rendered.
+// /// The control as html.
+// public override IHtmlNode Render(RenderContext context)
+// {
+// var module = ComponentManager.ModuleManager.GetModule(context.ApplicationContext, typeof(Module));
+// var code = $"updateTaskProgressBar('{Id}', '{module?.ContextPath.Append("api/v1/taskstatus")}', {OnFinishScript});";
- context.VisualTree.AddScript("webexpress.webapp:controlapiprogressbartaskstate", code);
+// context.VisualTree.AddScript("webexpress.webapp:controlapiprogressbartaskstate", code);
- return base.Render(context);
- }
- }
-}
+// return base.Render(context);
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiTable.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiTable.cs
index 9f612c9..8103ea8 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiTable.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiTable.cs
@@ -4,17 +4,21 @@
using System.Text;
using System.Text.Json;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
+using WebExpress.WebCore.WebUri;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebApiControl
{
+ ///
+ /// Represents a control panel for API table interactions.
+ ///
public class ControlApiTable : ControlPanel, IControlApi
{
///
/// Returns or sets the uri that determines the data.
///
- public string RestUri { get; set; }
+ public IUri RestUri { get; set; }
///
/// Returns or sets the settings for the editing options (e.g. Edit, Delete, ...).
@@ -27,7 +31,7 @@ public class ControlApiTable : ControlPanel, IControlApi
public ICollection OptionItems { get; private set; } = new List();
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlApiTable(string id = null)
@@ -38,11 +42,10 @@ public ControlApiTable(string id = null)
///
/// 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(RenderContext context, string id, string css)
+ protected virtual string GetScript(string id, string css)
{
var settings = new
{
@@ -68,11 +71,11 @@ protected virtual string GetScript(RenderContext context, string id, string css)
}
///
- /// Convert to html.
+ /// Converts the control to an HTML representation.
///
- /// 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, IVisualTreeControl visualTree)
{
var classes = Classes.ToList();
@@ -82,7 +85,7 @@ public override IHtmlNode Render(RenderContext context)
Style = GetStyles()
};
- context.VisualTree.AddScript(Id, GetScript(context, Id, string.Join(" ", classes)));
+ visualTree.AddScript(Id, GetScript(Id, string.Join(" ", classes)));
return html;
}
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiTableOption.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiTableOption.cs
index f8788d9..0eac6ca 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiTableOption.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiTableOption.cs
@@ -26,7 +26,7 @@ public class ControlApiTableOption
public string Color { get; set; }
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
public ControlApiTableOption()
{
diff --git a/src/WebExpress.WebApp/WebApiControl/ControlApiTableOptionItem.cs b/src/WebExpress.WebApp/WebApiControl/ControlApiTableOptionItem.cs
index 6649657..f37bb85 100644
--- a/src/WebExpress.WebApp/WebApiControl/ControlApiTableOptionItem.cs
+++ b/src/WebExpress.WebApp/WebApiControl/ControlApiTableOptionItem.cs
@@ -65,7 +65,7 @@ public enum OptionType { Item, Header, Divider };
public string OnClick { get; set; }
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
public ControlApiTableOptionItem()
{
@@ -73,7 +73,7 @@ public ControlApiTableOptionItem()
}
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The label of the column.
/// The type of option entry.
diff --git a/src/WebExpress.WebApp/WebApiControl/IControlApi.cs b/src/WebExpress.WebApp/WebApiControl/IControlApi.cs
index ef47ae4..758ba3c 100644
--- a/src/WebExpress.WebApp/WebApiControl/IControlApi.cs
+++ b/src/WebExpress.WebApp/WebApiControl/IControlApi.cs
@@ -1,10 +1,15 @@
-namespace WebExpress.WebApp.WebApiControl
+using WebExpress.WebCore.WebUri;
+
+namespace WebExpress.WebApp.WebApiControl
{
- internal interface IControlApi
+ ///
+ /// Interface for controlling API interactions.
+ ///
+ public interface IControlApi
{
///
/// Returns or sets the uri that determines the data.
///
- public string RestUri { get; set; }
+ public IUri RestUri { get; set; }
}
}
diff --git a/src/WebExpress.WebApp/WebCondition/ConditionUnix.cs b/src/WebExpress.WebApp/WebCondition/ConditionUnix.cs
index 22db781..74590ba 100644
--- a/src/WebExpress.WebApp/WebCondition/ConditionUnix.cs
+++ b/src/WebExpress.WebApp/WebCondition/ConditionUnix.cs
@@ -4,13 +4,16 @@
namespace WebExpress.WebApp.WebCondition
{
+ ///
+ /// Represents a condition that checks if the operating system is Unix.
+ ///
public class ConditionUnix : ICondition
{
///
- /// Die Bedingung
+ /// Check whether the condition is fulfilled.
///
/// The request.
- /// true wenn die Bedingung erfüllt ist, false sonst
+ /// True if the condition is fulfilled, false otherwise.
public bool Fulfillment(Request request)
{
return Environment.OSVersion.ToString().Contains("unix", StringComparison.OrdinalIgnoreCase);
diff --git a/src/WebExpress.WebApp/WebControl/ControlFormConfirm.cs b/src/WebExpress.WebApp/WebControl/ControlFormConfirm.cs
new file mode 100644
index 0000000..62970e7
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlFormConfirm.cs
@@ -0,0 +1,98 @@
+//using System;
+//using WebExpress.WebCore.Internationalization;
+//using WebExpress.WebCore.WebHtml;
+//using WebExpress.WebCore.WebPage;
+//using WebExpress.WebUI.WebControl;
+
+//namespace WebExpress.WebApp.WebControl
+//{
+// public class ControlFormConfirm : ControlForm
+// {
+// ///
+// /// Event is triggered when deletion is confirmed.
+// ///
+// public event EventHandler Confirm;
+
+// ///
+// /// Returns or sets the submit button icon.
+// ///
+// public PropertyIcon SubmitButtonIcon { get => SubmitButton.Icon; set => SubmitButton.Icon = value; }
+
+// ///
+// /// Returns or sets the submit button color.
+// ///
+// public PropertyColorButton SubmitButtonColor { get => SubmitButton.Color; set => SubmitButton.Color = value; }
+
+// ///
+// /// Returns or sets the submit button label.
+// ///
+// public string SubmitButtonLabel { get => SubmitButton.Text; set => SubmitButton.Text = value; }
+
+// ///
+// /// Returns or sets the submit button.
+// ///
+// private ControlFormItemButtonSubmit SubmitButton { get; set; }
+
+// ///
+// /// Returns or sets the content.
+// ///
+// public ControlFormItemStaticText Content { get; } = new ControlFormItemStaticText()
+// {
+// };
+
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlFormConfirm(string id = null)
+// : base(id, null)
+// {
+// SubmitButton = new ControlFormItemButtonSubmit("submit");
+// SubmitButtonColor = new PropertyColorButton(TypeColorButton.Primary);
+// }
+
+// ///
+// /// Triggers the confirm event.
+// ///
+// /// The context in which the control is rendered.
+// protected virtual void OnConfirm(RenderContextForm context)
+// {
+// Confirm?.Invoke(this, new FormEventArgs() { Context = context });
+// }
+
+// ///
+// /// Initializes the form.
+// ///
+// /// The context in which the control is rendered.
+// public override void Initialize(RenderContextForm context)
+// {
+// base.Initialize(context);
+
+// SubmitButtonLabel = context.Page.I18N("webexpress.webapp", "confirm.label");
+// Content.Text = context.Page.I18N("webexpress.webapp", "confirm.description");
+
+// Add(Content);
+// }
+
+// ///
+// /// Triggers the crocess event.
+// ///
+// /// The render context.
+// protected override void OnProcess(RenderContextForm context)
+// {
+// base.OnProcess(context);
+
+// OnConfirm(context);
+// }
+
+// ///
+// /// 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);
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebControl/ControlFormConfirmDelete.cs b/src/WebExpress.WebApp/WebControl/ControlFormConfirmDelete.cs
new file mode 100644
index 0000000..bc619f2
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlFormConfirmDelete.cs
@@ -0,0 +1,54 @@
+//using WebExpress.WebCore.Internationalization;
+//using WebExpress.WebCore.WebHtml;
+//using WebExpress.WebCore.WebPage;
+//using WebExpress.WebUI.WebControl;
+
+//namespace WebExpress.WebApp.WebControl
+//{
+// public class ControlFormConfirmDelete : ControlFormConfirm
+// {
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlFormConfirmDelete()
+// : this(null)
+// {
+// }
+
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlFormConfirmDelete(string id = null)
+// : base(id)
+// {
+// SubmitButtonIcon = new PropertyIcon(TypeIcon.TrashAlt);
+// SubmitButtonColor = new PropertyColorButton(TypeColorButton.Danger);
+// }
+
+// ///
+// /// Initializes the form.
+// ///
+// /// The context in which the control is rendered.
+// public override void Initialize(RenderContextForm context)
+// {
+// base.Initialize(context);
+
+// SubmitButtonLabel = context.Page.I18N("webexpress.webapp", "delete.label");
+// Content.Text = context.Page.I18N("webexpress.webapp", "delete.description");
+// }
+
+// ///
+// /// Convert to html.
+// ///
+// /// The context in which the control is rendered.
+// /// The control as html.
+// public override IHtmlNode Render(RenderContext context)
+// {
+// SubmitButtonLabel = context.Page.I18N("webexpress.webapp", "delete.label");
+
+// return base.Render(context);
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebControl/ControlFormularConfirm.cs b/src/WebExpress.WebApp/WebControl/ControlFormularConfirm.cs
deleted file mode 100644
index 91b1823..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlFormularConfirm.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using System;
-using WebExpress.WebCore.Internationalization;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- public class ControlFormularConfirm : ControlForm
- {
- ///
- /// Event is triggered when deletion is confirmed.
- ///
- public event EventHandler Confirm;
-
- ///
- /// Returns or sets the icon.
- ///
- public PropertyIcon ButtonIcon { get => SubmitButton.Icon; set => SubmitButton.Icon = value; }
-
- ///
- /// Returns or sets the color. der Schaltfläche
- ///
- public PropertyColorButton ButtonColor { get => SubmitButton.Color; set => SubmitButton.Color = value; }
-
- ///
- /// Returns or sets the label. der Schaltfläche
- ///
- public string ButtonLabel { get => SubmitButton.Text; set => SubmitButton.Text = value; }
-
- ///
- /// Returns or sets the content.
- ///
- public ControlFormItemStaticText Content { get; } = new ControlFormItemStaticText()
- {
- };
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlFormularConfirm(string id = null)
- : base(id, null)
- {
- ButtonColor = new PropertyColorButton(TypeColorButton.Primary);
- }
-
- ///
- /// Triggers the confirm event.
- ///
- /// The context in which the control is rendered.
- protected virtual void OnConfirm(RenderContextFormular context)
- {
- Confirm?.Invoke(this, new FormularEventArgs() { Context = context });
- }
-
- ///
- /// Initializes the form.
- ///
- /// The context in which the control is rendered.
- public override void Initialize(RenderContextFormular context)
- {
- base.Initialize(context);
-
- ButtonLabel = context.Page.I18N("webexpress.webapp", "confirm.label");
- Content.Text = context.Page.I18N("webexpress.webapp", "confirm.description");
- }
-
- ///
- /// Triggers the crocess event.
- ///
- ///
- protected override void OnProcess(RenderContextFormular context)
- {
- base.OnProcess(context);
-
- OnConfirm(context);
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- Items.Clear();
- Items.Add(Content);
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlFormularConfirmDelete.cs b/src/WebExpress.WebApp/WebControl/ControlFormularConfirmDelete.cs
deleted file mode 100644
index 7b580d2..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlFormularConfirmDelete.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using WebExpress.WebCore.Internationalization;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- public class ControlFormularConfirmDelete : ControlFormularConfirm
- {
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlFormularConfirmDelete()
- : this(null)
- {
- }
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlFormularConfirmDelete(string id = null)
- : base(id)
- {
- ButtonIcon = new PropertyIcon(TypeIcon.TrashAlt);
- ButtonColor = new PropertyColorButton(TypeColorButton.Danger);
- }
-
- ///
- /// Initializes the form.
- ///
- /// The context in which the control is rendered.
- public override void Initialize(RenderContextFormular context)
- {
- base.Initialize(context);
-
- ButtonLabel = context.Page.I18N("webexpress.webapp", "delete.label");
- Content.Text = context.Page.I18N("webexpress.webapp", "delete.description");
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- ButtonLabel = context.Page.I18N("webexpress.webapp", "delete.label");
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormConfirm.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormConfirm.cs
new file mode 100644
index 0000000..9be4871
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlModalFormConfirm.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebCore.WebIcon;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a modal confirmation form.
+ ///
+ public class ControlModalFormConfirm : ControlModalForm
+ {
+ ///
+ /// Event is triggered when deletion is confirmed.
+ ///
+ public event EventHandler Confirm;
+
+ ///
+ /// Returns or sets the submit button icon.
+ ///
+ public IIcon SubmitButtonIcon { get { return SubmitButton?.Icon; } set { SubmitButton.Icon = value; } }
+
+ ///
+ /// Returns or sets the submit button color.
+ ///
+ public PropertyColorButton SubmitButtonColor { get { return SubmitButton?.Color; } set { SubmitButton.Color = value; } }
+
+ ///
+ /// Returns or sets the submit button label.
+ ///
+ public string SubmitButtonLabel { get; set; }
+
+ ///
+ /// Returns or sets the content.
+ ///
+ public new ControlFormItem Content { get; set; }
+
+ ///
+ /// Returns or sets the submit button.
+ ///
+ private ControlFormItemButtonSubmit SubmitButton { get; } = new ControlFormItemButtonSubmit("submit");
+
+ ///
+ /// Returns or sets the redirect uri.
+ ///
+ public string RedirectUri { get { return Form?.RedirectUri; } set { Form.RedirectUri = value; } }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The id.
+ public ControlModalFormConfirm(string id = null, params ControlFormItem[] content)
+ : base(id, content)
+ {
+ Form.ProcessForm += (s, e) =>
+ {
+ OnConfirm(e.Context);
+ };
+
+ Form.AddPrimaryButton(SubmitButton);
+ }
+
+ ///
+ /// Triggers the confirm event.
+ ///
+ /// The context in which the control is rendered.
+ protected virtual void OnConfirm(IRenderControlFormContext context)
+ {
+ Confirm?.Invoke(this, new FormEventArgs() { Context = context });
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var content = Content ?? new ControlFormItemStaticText()
+ {
+ Text = I18N.Translate(renderContext.Request, "webexpress.webapp:confirm.description")
+ };
+
+ return Render(renderContext, visualTree, [content]);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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 override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree, IEnumerable items)
+ {
+ if (string.IsNullOrWhiteSpace(Header))
+ {
+ Header = I18N.Translate(renderContext.Request, "webexpress.webapp:confirm.header");
+ }
+
+ if (string.IsNullOrWhiteSpace(SubmitButtonLabel))
+ {
+ SubmitButtonLabel = I18N.Translate(renderContext.Request, "webexpress.webapp:confirm.label");
+ }
+
+ Form.RedirectUri = RedirectUri ?? renderContext.Request.Uri;
+ SubmitButton.Text = SubmitButtonLabel;
+
+ return base.Render(renderContext, visualTree, items);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormConfirmDelete.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormConfirmDelete.cs
new file mode 100644
index 0000000..3f99996
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlModalFormConfirmDelete.cs
@@ -0,0 +1,55 @@
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a modal confirmation form specifically for delete actions.
+ ///
+ public class ControlModalFormConfirmDelete : ControlModalFormConfirm
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlModalFormConfirmDelete(string id = null)
+ : this(id, null)
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ /// The form controls.
+ public ControlModalFormConfirmDelete(string id, params ControlFormItem[] content)
+ : base(id, content)
+ {
+ SubmitButtonIcon = new IconTrash();
+ SubmitButtonColor = new PropertyColorButton(TypeColorButton.Danger);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ if (string.IsNullOrWhiteSpace(Header))
+ {
+ Header = I18N.Translate(renderContext, "webexpress.webapp:delete.header");
+ }
+
+ SubmitButtonLabel ??= I18N.Translate(renderContext, "webexpress.webapp:delete.label");
+ Content ??= new ControlFormItemStaticText() { Text = I18N.Translate(renderContext, "webexpress.webapp:delete.description") };
+
+ return base.Render(renderContext, visualTree);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormFileUpload.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormFileUpload.cs
new file mode 100644
index 0000000..ced1ee2
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlModalFormFileUpload.cs
@@ -0,0 +1,161 @@
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using WebExpress.WebCore.WebHtml;
+//using WebExpress.WebCore.WebMessage;
+//using WebExpress.WebCore.WebPage;
+//using WebExpress.WebUI.WebControl;
+//using static WebExpress.WebCore.Internationalization.InternationalizationManager;
+
+//namespace WebExpress.WebApp.WebControl
+//{
+// public class ControlModalFormFileUpload : ControlModalForm
+// {
+// ///
+// /// Returns or sets the files that are accepted.
+// ///
+// public ICollection AcceptFile { get => File.AcceptFile; set => File.AcceptFile = value; }
+
+// ///
+// /// Event is triggered when the upload is confirmed.
+// ///
+// public event EventHandler Upload;
+
+// ///
+// /// Returns or sets the document.
+// ///
+// public ControlFormItemInputFile File { get; } = new ControlFormItemInputFile()
+// {
+// Name = "file",
+// Help = "webexpress.webapp:fileupload.file.description",
+// //Icon = new PropertyIcon(TypeIcon.Image),
+// //AcceptFile = new string[] { "image/*, video/*, audio/*, .pdf, .doc, .docx, .txt" },
+// Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three)
+// };
+
+// ///
+// /// Returns or sets the submit button icon.
+// ///
+// public PropertyIcon SubmitButtonIcon { get { return SubmitButton?.Icon; } set { SubmitButton.Icon = value; } }
+
+// ///
+// /// Returns or sets the submit button color.
+// ///
+// public PropertyColorButton SubmitButtonColor { get { return SubmitButton?.Color; } set { SubmitButton.Color = value; } }
+
+// ///
+// /// Returns or sets the submit button label.
+// ///
+// public string SubmitButtonLabel { get { return SubmitButton?.Text; } set { SubmitButton.Text = value; } }
+
+// ///
+// /// Returns or sets the prologue area.
+// ///
+// public ControlFormItem Prologue { get; set; }
+
+// ///
+// /// Returns or sets the epilogue area.
+// ///
+// public ControlFormItem Epilogue { get; set; }
+
+// ///
+// /// Returns or sets the redirect uri.
+// ///
+// public string RedirectUri { get { return Form?.RedirectUri; } set { Form.RedirectUri = value; } }
+
+// ///
+// /// Returns or sets the submit button.
+// ///
+// private ControlFormItemButtonSubmit SubmitButton { get; set; }
+
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// public ControlModalFormFileUpload(string id = null)
+// : this(id, null)
+// {
+// }
+
+// ///
+// /// Initializes a new instance of the class.
+// ///
+// /// The control id.
+// /// The form controls.
+// public ControlModalFormFileUpload(string id, params ControlFormItem[] content)
+// : base(id, string.Empty, content)
+// {
+// Init();
+// }
+
+// ///
+// /// Initialization
+// ///
+// private void Init()
+// {
+// SubmitButton = new ControlFormItemButtonSubmit("submit");
+// Header = I18N("webexpress.webapp:fileupload.header");
+// SubmitButtonLabel = I18N("webexpress.webapp:fileupload.label");
+// SubmitButtonIcon = new PropertyIcon(TypeIcon.Upload);
+// SubmitButtonColor = new PropertyColorButton(TypeColorButton.Primary);
+
+// File.Validation += OnValidationFile;
+// Form.ProcessForm += OnProcessForm;
+
+// Form.Add(File);
+// Form.AddPrimaryButton(SubmitButton);
+
+// }
+
+// ///
+// /// Validation of the upload file.
+// ///
+// /// The trigger of the event.
+// /// The event argument.
+// private void OnValidationFile(object sender, ValidationEventArgs e)
+// {
+// if (!(e.Context.Request.GetParameter(File.Name) is ParameterFile))
+// {
+// e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:fileupload.file.validation.error.nofile"));
+// }
+// }
+
+// ///
+// /// Processing of the form.
+// ///
+// /// The trigger of the event.
+// /// The event argument.
+// private void OnProcessForm(object sender, FormEventArgs e)
+// {
+// if (e.Context.Request.GetParameter(File.Name) is ParameterFile file)
+// {
+// OnUpload(new FormUploadEventArgs(e) { File = file });
+// }
+// }
+
+// ///
+// /// Löst das Upload-Event aus
+// ///
+// /// The event argument.
+// protected virtual void OnUpload(FormUploadEventArgs args)
+// {
+// Upload?.Invoke(this, args);
+// }
+
+// ///
+// /// Convert to html.
+// ///
+// /// The context in which the control is rendered.
+// /// The control as html.
+// public override IHtmlNode Render(RenderContext context)
+// {
+// Form.RedirectUri = RedirectUri ?? context.Uri;
+
+// var list = new[] { Epilogue }
+// .Concat(Form.Items)
+// .Concat([Prologue]);
+
+// return base.Render(context, list.Where(x => x != null));
+// }
+// }
+//}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirm.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirm.cs
deleted file mode 100644
index 55a0efa..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirm.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-using System;
-using WebExpress.WebCore.Internationalization;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- public class ControlModalFormularConfirm : ControlModalFormular
- {
- ///
- /// Event is triggered when deletion is confirmed.
- ///
- public event EventHandler Confirm;
-
- ///
- /// Returns or sets the icon.
- ///
- public PropertyIcon ButtonIcon { get; set; }
-
- ///
- /// Returns or sets the color. der Schaltfläche
- ///
- public PropertyColorButton ButtonColor { get; set; }
-
- ///
- /// Returns or sets the label. der Schaltfläche
- ///
- public string ButtonLabel { get; set; }
-
- ///
- /// Returns or sets the content.
- ///
- public new ControlFormItem Content { get; set; }
-
- ///
- /// Returns or sets the redirect uri.
- ///
- public string RedirectUri { get { return Formular?.RedirectUri; } set { Formular.RedirectUri = value; } }
-
- ///
- /// Constructor
- ///
- /// The id.
- public ControlModalFormularConfirm(string id = null)
- : this(id, null)
- {
-
- }
-
- ///
- /// Constructor
- ///
- /// The id.
- /// Die Formularsteuerelemente
- public ControlModalFormularConfirm(string id, params ControlFormItem[] content)
- : base(id, string.Empty, content)
- {
- Init();
- }
-
- ///
- /// Initialization
- ///
- private void Init()
- {
- Formular.ProcessFormular += (s, e) =>
- {
- OnConfirm(e.Context);
- };
- }
-
- ///
- /// Triggers the Confirm event.
- ///
- /// The context in which the control is rendered.
- protected virtual void OnConfirm(RenderContextFormular context)
- {
- Confirm?.Invoke(this, new FormularEventArgs() { Context = context });
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- if (string.IsNullOrWhiteSpace(Header))
- {
- Header = context.Page.I18N("webexpress.webapp", "confirm.header");
- }
-
- if (string.IsNullOrWhiteSpace(ButtonLabel))
- {
- ButtonLabel = context.Page.I18N("webexpress.webapp", "confirm.label");
- }
-
- if (Content == null)
- {
- Content = new ControlFormItemStaticText() { Text = context.Page.I18N("webexpress.webapp", "confirm.description") };
- }
-
- if (ButtonColor == null)
- {
- ButtonColor = new PropertyColorButton(TypeColorButton.Primary);
- }
-
- Formular.RedirectUri = RedirectUri ?? context.Uri;
- Formular.SubmitButton.Text = ButtonLabel;
- Formular.SubmitButton.Icon = ButtonIcon;
- Formular.SubmitButton.Color = ButtonColor;
- Formular.Items.Clear();
- Formular.Add(Content);
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirmDelete.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirmDelete.cs
deleted file mode 100644
index 3a1a6d5..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularConfirmDelete.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using WebExpress.WebCore.Internationalization;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- public class ControlModalFormularConfirmDelete : ControlModalFormularConfirm
- {
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularConfirmDelete(string id = null)
- : this(id, null)
- {
-
- }
-
- ///
- /// Constructor
- ///
- /// The control id.
- /// Die Formularsteuerelemente
- public ControlModalFormularConfirmDelete(string id, params ControlFormItem[] content)
- : base(id, content)
- {
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- if (string.IsNullOrWhiteSpace(Header))
- {
- Header = context.Page.I18N("webexpress.webapp", "delete.header");
- }
-
- if (string.IsNullOrWhiteSpace(ButtonLabel))
- {
- ButtonLabel = context.Page.I18N("webexpress.webapp", "delete.label");
- }
-
- if (Content == null)
- {
- Content = new ControlFormItemStaticText() { Text = context.Page.I18N("webexpress.webapp", "delete.description") };
- }
-
- if (ButtonIcon == null)
- {
- ButtonIcon = new PropertyIcon(TypeIcon.TrashAlt);
- }
-
- if (ButtonColor == null)
- {
- ButtonColor = new PropertyColorButton(TypeColorButton.Danger);
- }
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularFileUpload.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularFileUpload.cs
deleted file mode 100644
index ac3bd66..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularFileUpload.cs
+++ /dev/null
@@ -1,170 +0,0 @@
-using System;
-using System.Collections.Generic;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebMessage;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebUI.WebControl;
-using static WebExpress.WebCore.Internationalization.InternationalizationManager;
-
-namespace WebExpress.WebApp.WebControl
-{
- public class ControlModalFormularFileUpload : ControlModalFormular
- {
- ///
- /// Returns or sets the files that are accepted.
- ///
- public ICollection AcceptFile { get => File.AcceptFile; set => File.AcceptFile = value; }
-
- ///
- /// Event is triggered when the upload is confirmed.
- ///
- public event EventHandler Upload;
-
- ///
- /// Returns or sets the document.
- ///
- public ControlFormItemInputFile File { get; } = new ControlFormItemInputFile()
- {
- Name = "file",
- Help = "webexpress.webapp:fileupload.file.description",
- //Icon = new PropertyIcon(TypeIcon.Image),
- //AcceptFile = new string[] { "image/*, video/*, audio/*, .pdf, .doc, .docx, .txt" },
- Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.Three)
- };
-
- ///
- /// Returns or sets the icon.
- ///
- public PropertyIcon ButtonIcon { get; set; }
-
- ///
- /// Returns or sets the button color.
- ///
- public PropertyColorButton ButtonColor { get; set; }
-
- ///
- /// Returns or sets the button label.
- ///
- public string ButtonLabel { get; set; }
-
- ///
- /// Teh prologue.
- ///
- private ControlFormItem prologue;
-
- ///
- /// Returns or sets the prologue area.
- ///
- public ControlFormItem Prologue
- {
- get => prologue;
- set { Formular.Items.Remove(prologue); prologue = value; Formular.Items.Insert(0, prologue); }
- }
-
- ///
- /// The epilogue.
- ///
- private ControlFormItem epilogue;
-
-
- ///
- /// Returns or sets the epilogue area.
- ///
- public ControlFormItem Epilogue
- {
- get => epilogue;
- set { Formular.Items.Remove(epilogue); epilogue = value; Formular.Items.Add(epilogue); }
- }
-
- ///
- /// Returns or sets the redirect uri.
- ///
- public string RedirectUri { get { return Formular?.RedirectUri; } set { Formular.RedirectUri = value; } }
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularFileUpload(string id = null)
- : this(id, null)
- {
- }
-
- ///
- /// Constructor
- ///
- /// The control id.
- /// Die Formularsteuerelemente
- public ControlModalFormularFileUpload(string id, params ControlFormItem[] content)
- : base(id, string.Empty, content)
- {
- Init();
- }
-
- ///
- /// Initialization
- ///
- private void Init()
- {
- Header = I18N("webexpress.webapp:fileupload.header");
- ButtonLabel = I18N("webexpress.webapp:fileupload.label");
- ButtonIcon = new PropertyIcon(TypeIcon.Upload);
- ButtonColor = new PropertyColorButton(TypeColorButton.Primary);
-
- File.Validation += OnValidationFile;
- Formular.ProcessFormular += OnProcessFormular;
-
- Formular.Add(File);
- }
-
- ///
- /// Validation of the upload file.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnValidationFile(object sender, ValidationEventArgs e)
- {
- if (!(e.Context.Request.GetParameter(File.Name) is ParameterFile))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:fileupload.file.validation.error.nofile"));
- }
- }
-
- ///
- /// Processing of the resource. des Formulares
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnProcessFormular(object sender, FormularEventArgs e)
- {
- if (e.Context.Request.GetParameter(File.Name) is ParameterFile file)
- {
- OnUpload(new FormularUploadEventArgs(e) { File = file });
- }
- }
-
- ///
- /// Löst das Upload-Event aus
- ///
- /// The event argument.
- protected virtual void OnUpload(FormularUploadEventArgs args)
- {
- Upload?.Invoke(this, args);
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- Formular.RedirectUri = RedirectUri ?? context.Uri;
- Formular.SubmitButton.Text = ButtonLabel;
- Formular.SubmitButton.Icon = ButtonIcon;
- Formular.SubmitButton.Color = ButtonColor;
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupEdit.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupEdit.cs
deleted file mode 100644
index b91777e..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupEdit.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using System;
-using System.Linq;
-using WebExpress.WebApp.WebUser;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularGoupEdit : ControlModalFormular
- {
- ///
- /// Returns or sets the group to be deleted.
- ///
- public Group Item { get; set; }
-
- ///
- /// Returns the description of the form.
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText()
- {
- Text = "webexpress.webapp:setting.usermanager.group.edit.description",
- TextColor = new PropertyColorText(TypeColorText.Secondary)
- };
-
- ///
- /// Returns the control element for entering the group name.
- ///
- private ControlFormItemInputTextBox GroupName { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.group.edit.name.label",
- Name = "groupname"
- };
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularGoupEdit(string id = null)
- : base(id)
- {
- Add(Description);
- Add(GroupName);
-
- Header = "webexpress.webapp:setting.usermanager.group.edit.header";
-
- GroupName.Validation += OnGroupNameValidation;
- Formular.SubmitButton.Text = "webexpress.webapp:setting.usermanager.group.edit.confirm";
- Formular.FillFormular += OnFillFormular;
- Formular.ProcessFormular += OnConfirm;
- }
-
- ///
- /// Invoked when the form is to be filled with initial values.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnFillFormular(object sender, FormularEventArgs e)
- {
- GroupName.Value = Item?.Name;
- }
-
- ///
- /// Invoked when you want to check the group name you entered.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnGroupNameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(GroupName.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.group.edit.name.error.empty"));
- }
-
- if (UserManager.Groups.Where(x => x != Item && x.Name.Equals(GroupName.Value, StringComparison.OrdinalIgnoreCase)).Any())
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.group.edit.name.error.duplicate"));
- }
- }
-
- ///
- /// Called when the delete action has been confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- Item.Name = GroupName.Value;
-
- UserManager.UpdateGroup(Item);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupNew.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupNew.cs
deleted file mode 100644
index c0243d0..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularGoupNew.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System;
-using System.Linq;
-using WebExpress.WebApp.WebUser;
-using WebExpress.WebUI.WebControl;
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularGoupNew : ControlModalFormular
- {
- ///
- /// Returns the description of the form.
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText()
- {
- Text = "webexpress.webapp:setting.usermanager.group.add.description",
- TextColor = new PropertyColorText(TypeColorText.Secondary)
- };
-
- ///
- /// Returns the control element for entering the group name.
- ///
- private ControlFormItemInputTextBox GroupName { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.group.add.name.label",
- Name = "groupname"
- };
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularGoupNew(string id = null)
- : base(id)
- {
- Add(Description);
- Add(GroupName);
-
- Header = "webexpress.webapp:setting.usermanager.group.add.header";
-
- GroupName.Validation += OnGroupNameValidation;
- Formular.SubmitButton.Text = "webexpress.webapp:setting.usermanager.group.add.confirm";
- Formular.ProcessFormular += OnConfirm;
- }
-
- ///
- /// Invoked when you want to check the group name you entered.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnGroupNameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(GroupName.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.group.add.name.error.empty"));
- }
-
- if (UserManager.Groups.Where(x => x.Name.Equals(GroupName.Value, StringComparison.OrdinalIgnoreCase)).Any())
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.group.add.name.error.duplicate"));
- }
- }
-
- ///
- /// Called when the delete action has been confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- var group = new Group()
- {
- Id = Guid.NewGuid().ToString(),
- Name = GroupName.Value,
- Created = DateTime.Now,
- Updated = DateTime.Now
- };
-
- UserManager.AddGroup(group);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularGroupDelete.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularGroupDelete.cs
deleted file mode 100644
index 60051b2..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularGroupDelete.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebUser;
-using WebExpress.WebUI.WebControl;
-using static WebExpress.WebCore.Internationalization.InternationalizationManager;
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularGroupDelete : ControlModalFormularConfirmDelete
- {
- ///
- /// Returns or sets the group to be edited.
- ///
- public Group Item { get; set; }
-
- ///
- /// Returns the description.
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText();
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularGroupDelete(string id = null)
- : base("delete_" + id)
- {
- Confirm += OnConfirm;
-
- Header = "webexpress.webapp:setting.usermanager.group.delete.header";
- Content = Description;
- }
-
- ///
- /// Invoked when the deletion is confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- ///
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- UserManager.RemoveGroup(Item);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- Description.Text = string.Format(I18N(context.Culture, "webexpress.webapp:setting.usermanager.group.delete.description"), Item.Name);
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserDelete.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularUserDelete.cs
deleted file mode 100644
index 0425258..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserDelete.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebUser;
-using WebExpress.WebUI.WebControl;
-using static WebExpress.WebCore.Internationalization.InternationalizationManager;
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularUserDelete : ControlModalFormularConfirmDelete
- {
- ///
- /// Returns or sets the user to be deleted.
- ///
- public User Item { get; set; }
-
- ///
- /// Returns the description.
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText();
-
- ///
- /// Constructor
- ///
- /// The control id.
- public ControlModalFormularUserDelete(string id = null)
- : base("delete_" + id)
- {
- Confirm += OnConfirm;
-
- Header = "webexpress.webapp:setting.usermanager.user.delete.header";
- Content = Description;
- }
-
- ///
- /// Invoked when the deletion is confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- UserManager.RemoveUser(Item);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- Description.Text = string.Format(I18N(context.Culture, "webexpress.webapp:setting.usermanager.user.delete.description"), Item.Login);
-
- return base.Render(context);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserEdit.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularUserEdit.cs
deleted file mode 100644
index 15b8b31..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserEdit.cs
+++ /dev/null
@@ -1,203 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using WebExpress.WebUI.WebControl;
-using WebExpress.WebApp.WebUser;
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularUserEdit : ControlModalFormular
- {
- ///
- /// Der zu bearbeitende Benutzer
- ///
- public User Item { get; set; }
-
- ///
- /// Liefert die Beschreibung des Formulars
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText()
- {
- Text = "webexpress.webapp:setting.usermanager.user.edit.description",
- TextColor = new PropertyColorText(TypeColorText.Secondary)
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe der Loginkennung
- ///
- private ControlFormItemInputTextBox Login { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.edit.login.label",
- Name = "login"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe des Vornamens
- ///
- private ControlFormItemInputTextBox Firstname { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.edit.firstname.label",
- Name = "firstname"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe des Nachnamens
- ///
- private ControlFormItemInputTextBox Lastname { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.edit.lastname.label",
- Name = "lastname"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe der Email-Adresse
- ///
- private ControlFormItemInputTextBox Email { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.edit.email.label",
- Name = "email",
- Placeholder = "user@example.com"
- };
-
- ///
- /// Liefert die Gruppen
- ///
- private ControlFormItemInputMove Groups { get; set; }
-
- ///
- /// Constructor
- ///
- /// The id.
- public ControlModalFormularUserEdit(string id = null)
- : base(id)
- {
- Groups = new ControlFormItemInputMove(id)
- {
- Name = "groups",
- Label = "webexpress.webapp:setting.usermanager.user.edit.groups.label",
- Help = "webexpress.webapp:setting.usermanager.user.edit.groups.description",
- SelectedHeader = "webexpress.webapp:setting.usermanager.user.edit.groups.selected",
- AvailableHeader = "webexpress.webapp:setting.usermanager.user.edit.groups.available",
- Icon = new PropertyIcon(TypeIcon.Users)
- };
-
- Login.Validation += OnLoginValidation;
- Firstname.Validation += OnFirstnameValidation;
- Lastname.Validation += OnLastnameValidation;
- Email.Validation += OnEmailValidation;
-
- Add(Description);
- Add(Login);
- Add(new ControlFormItemGroupColumnVertical(Firstname, Lastname) { Distribution = new int[] { 50 } });
- Add(Email);
- Add(Groups);
- Formular.SubmitButton.Text = "webexpress.webapp:setting.usermanager.user.edit.confirm";
- Formular.FillFormular += OnFillFormular;
- Formular.ProcessFormular += OnConfirm;
-
- Header = "webexpress.webapp:setting.usermanager.user.edit.header";
- }
-
- ///
- /// Invoked when the form is to be filled with initial values.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnFillFormular(object sender, FormularEventArgs e)
- {
- Login.Value = Item?.Login;
- Firstname.Value = Item?.Firstname;
- Lastname.Value = Item?.Lastname;
- Email.Value = Item?.Email;
-
- foreach (var v in UserManager.Groups.OrderBy(x => x.Name))
- {
- Groups.Options.Add(new ControlFormItemInputSelectionItem()
- {
- Id = v.Id,
- Label = v.Name
- });
- }
-
- Groups.Value = string.Join(";", Item.GroupIds);
- }
-
- ///
- /// Wird aufgerufen, wenn die eingegebene Loginkennung überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnLoginValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Login.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.edit.login.error.empty"));
- }
-
- if (UserManager.Users.Where(x => x != Item && x.Login.Equals(Login.Value, StringComparison.OrdinalIgnoreCase)).Any())
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.edit.login.error.duplicate"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn der eingegebene Vorname überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnFirstnameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Firstname.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.edit.firstname.error.empty"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn der eingegebene Nachname überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnLastnameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Lastname.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.edit.lastname.error.empty"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn die eingegebene E-Mail-Adresse überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnEmailValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Email.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.edit.email.error.empty"));
- }
- }
-
- ///
- /// Called when the delete action has been confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- Item.Login = Login.Value;
- Item.Firstname = Firstname.Value;
- Item.Lastname = Lastname.Value;
- Item.Email = Email.Value;
-
- var groups = Groups.Value?.Split(";", StringSplitOptions.RemoveEmptyEntries);
- Item.GroupIds = new List();
- Item.GroupIds.AddRange(groups);
-
- UserManager.UpdateUser(Item);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserNew.cs b/src/WebExpress.WebApp/WebControl/ControlModalFormularUserNew.cs
deleted file mode 100644
index a3932b8..0000000
--- a/src/WebExpress.WebApp/WebControl/ControlModalFormularUserNew.cs
+++ /dev/null
@@ -1,191 +0,0 @@
-using System;
-using System.Linq;
-using WebExpress.WebApp.WebUser;
-using WebExpress.WebUI.WebControl;
-
-
-namespace WebExpress.WebApp.WebControl
-{
- internal sealed class ControlModalFormularUserNew : ControlModalFormular
- {
- ///
- /// Liefert die Beschreibung des Formulars
- ///
- private ControlFormItemStaticText Description { get; } = new ControlFormItemStaticText()
- {
- Text = "webexpress.webapp:setting.usermanager.user.add.description",
- TextColor = new PropertyColorText(TypeColorText.Secondary)
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe der Loginkennung
- ///
- private ControlFormItemInputTextBox Login { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.add.login.label",
- Name = "login"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe des Vornamens
- ///
- private ControlFormItemInputTextBox Firstname { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.add.firstname.label",
- Name = "firstname"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe des Nachnamens
- ///
- private ControlFormItemInputTextBox Lastname { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.add.lastname.label",
- Name = "lastname"
- };
-
- ///
- /// Liefert das Steuerlement zur Eingabe der Email-Adresse
- ///
- private ControlFormItemInputTextBox Email { get; } = new ControlFormItemInputTextBox()
- {
- Label = "webexpress.webapp:setting.usermanager.user.add.email.label",
- Name = "email",
- Placeholder = "user@example.com"
- };
-
- ///
- /// Liefert die Gruppen
- ///
- private ControlFormItemInputMove Groups { get; } = new ControlFormItemInputMove("group")
- {
- Name = "groups",
- Label = "webexpress.webapp:setting.usermanager.user.edit.groups.label",
- Help = "webexpress.webapp:setting.usermanager.user.edit.groups.description",
- SelectedHeader = "webexpress.webapp:setting.usermanager.user.edit.groups.selected",
- AvailableHeader = "webexpress.webapp:setting.usermanager.user.edit.groups.available",
- Icon = new PropertyIcon(TypeIcon.Users)
- };
-
- ///
- /// Constructor
- ///
- /// The id.
- public ControlModalFormularUserNew(string id = null)
- : base(id)
- {
- Login.Validation += OnLoginValidation;
- Firstname.Validation += OnFirstnameValidation;
- Lastname.Validation += OnLastnameValidation;
- Email.Validation += OnEmailValidation;
-
- Add(Description);
- Add(Login);
- Add(new ControlFormItemGroupColumnVertical(Firstname, Lastname) { Distribution = new int[] { 50 } });
- Add(Email);
- Add(Groups);
- Formular.SubmitButton.Text = "webexpress.webapp:setting.usermanager.user.add.confirm";
- Formular.FillFormular += OnFillFormular;
- Formular.ProcessFormular += OnConfirm;
-
- Header = "webexpress.webapp:setting.usermanager.user.add.header";
- }
-
- ///
- /// Invoked when the form is to be filled with initial values.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnFillFormular(object sender, FormularEventArgs e)
- {
- foreach (var v in UserManager.Groups.OrderBy(x => x.Name))
- {
- Groups.Options.Add(new ControlFormItemInputSelectionItem()
- {
- Id = v.Id,
- Label = v.Name
- });
- }
- }
-
- ///
- /// Wird aufgerufen, wenn die eingegebene Loginkennung überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnLoginValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Login.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.add.login.error.empty"));
- }
-
- if (UserManager.Users.Where(x => x.Login.Equals(Login.Value, StringComparison.OrdinalIgnoreCase)).Any())
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.add.login.error.duplicate"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn der eingegebene Vorname überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnFirstnameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Firstname.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.add.firstname.error.empty"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn der eingegebene Nachname überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnLastnameValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Lastname.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.add.lastname.error.empty"));
- }
- }
-
- ///
- /// Wird aufgerufen, wenn die eingegebene E-Mail-Adresse überprüft werden soll
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnEmailValidation(object sender, ValidationEventArgs e)
- {
- if (string.IsNullOrWhiteSpace(Email.Value))
- {
- e.Results.Add(new ValidationResult(TypesInputValidity.Error, "webexpress.webapp:setting.usermanager.user.add.email.error.empty"));
- }
- }
-
- ///
- /// Called when the delete action has been confirmed.
- ///
- /// The trigger of the event.
- /// The event argument.
- private void OnConfirm(object sender, FormularEventArgs e)
- {
- var user = new User()
- {
- Id = Guid.NewGuid(),
- Login = Login.Value,
- Firstname = Firstname.Value,
- Lastname = Lastname.Value,
- Email = Email.Value,
- Created = DateTime.Now,
- Updated = DateTime.Now
- };
-
- UserManager.AddUser(user);
-
- e.Context.Page.Redirecting(e.Context.Uri);
- }
- }
-}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppContent.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppContent.cs
index 61d59ae..06aef0d 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppContent.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppContent.cs
@@ -1,126 +1,66 @@
-using System.Collections.Generic;
-using System.Linq;
-using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
+using WebExpress.WebCore.WebHtml;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
///
- /// Content of a web app page.
+ /// Represents the content control for a web application.
///
- public class ControlWebAppContent : ControlPanel
+ public class ControlWebAppContent : Control
{
///
- /// Returns the main panel.
+ /// Returns the toolbar.
///
- private ControlPanelMain MainPanel { get; } = new ControlPanelMain("webexpress.webapp.content.main")
- {
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Two, PropertySpacing.Space.Null),
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Null, PropertySpacing.Space.Two, PropertySpacing.Space.Null, PropertySpacing.Space.Null),
- BackgroundColor = LayoutSchema.ContentBackground,
- Classes = new() { "flex-grow-1" }
- };
+ public ControlWebAppToolbar Toolbar { get; } = new ControlWebAppToolbar("wx-content-toolbar");
///
- /// Returns the flexbox.
+ /// Returns the main panel.
///
- private ControlPanelFlexbox Flexbox { get; } = new ControlPanelFlexbox()
+ public ControlWebAppMain MainPanel { get; } = new ControlWebAppMain("wx-content-main")
{
- Layout = TypeLayoutFlexbox.Default,
- Align = TypeAlignFlexbox.Stretch
+ //BackgroundColor = new PropertyColorBackground(TypeColorBackground.Danger),
};
///
/// Returns the page properties.
///
- public ControlWebAppProperty Property { get; } = new ControlWebAppProperty("webexpress.webapp.content.property");
-
- ///
- /// Returns the toolbar.
- ///
- public ControlToolbar Toolbar { get; } = new ControlToolbar("webexpress.webapp.content.toolbar");
-
- ///
- /// Returns the headline control.
- ///
- public ControlWebAppHeadline Headline { get; } = new ControlWebAppHeadline("webexpress.webapp.content.main.headline");
-
- ///
- /// Returns the preferences area.
- ///
- public List Preferences { get; } = new List();
-
- ///
- /// Returns the primary area.
- ///
- public List Primary { get; } = new List();
+ public ControlWebAppProperty Property { get; } = new ControlWebAppProperty("wx-content-property");
///
- /// Returns the secondary area.
- ///
- public List Secondary { get; } = new List();
-
- ///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppContent(string id = null)
: base(id)
{
- Init();
-
- Classes.Add("content");
}
///
- /// Initialization
+ /// Converts the control to an HTML representation.
///
- private void Init()
+ /// 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, IVisualTreeControl visualTree)
{
- BackgroundColor = LayoutSchema.ContentBackground;
- Toolbar.BackgroundColor = LayoutSchema.ToolbarBackground;
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Two);
-
- Flexbox.Content.Add(MainPanel);
- Flexbox.Content.Add(Property);
-
- Content.Add(Toolbar);
- Content.Add(Flexbox);
- }
-
- ///
- /// Convert to html.
- ///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
- {
- MainPanel.Content.Clear();
-
- MainPanel.Content.Add(Headline);
- MainPanel.Content.Add(new ControlPanel("webexpress.webapp.content.main.preferences", Preferences));
- MainPanel.Content.Add(new ControlPanel("webexpress.webapp.content.main.primary", Primary));
- MainPanel.Content.Add(new ControlPanel("webexpress.webapp.content.main.secondary", Secondary));
-
- Content.Clear();
-
- if (Toolbar.Items.Any())
- {
- Content.Add(Toolbar);
- }
-
- if (Property.Preferences.Any() || Property.Primary.Any() || Property.Secondary.Any())
- {
- Content.Add(Flexbox);
- }
- else
+ var contentCtlr = new ControlPanel
+ (
+ Id,
+ Toolbar,
+ new ControlPanelFlexbox(null, MainPanel, Property)
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Stretch,
+ FlexGrow = TypeFlexGrow.Grow
+ }
+ )
{
- Content.Add(MainPanel);
- }
+ Classes = ["wx-content"],
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two)
+ };
- return base.Render(context);
+ return contentCtlr?.Render(renderContext, visualTree);
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppFooter.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppFooter.cs
index 88da476..fc32265 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppFooter.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppFooter.cs
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.Linq;
-using WebExpress.WebApp.WebPage;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -12,61 +14,126 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppFooter : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppFooter(string id = null)
: base(id)
{
- Init();
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControl[] items)
{
- BackgroundColor = LayoutSchema.FooterBackground;
- TextColor = LayoutSchema.FooterText;
+ _preferences.AddRange(items);
}
///
- /// Convert to html.
+ /// Removes an item from the preferences area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControl item)
{
- var elements = new List
- {
- new HtmlElementTextContentDiv(Preferences.Select(x => x.Render(context))),
- new HtmlElementTextContentDiv(Primary.Select(x => x.Render(context))) { Class = "justify-content-center" },
- new HtmlElementTextContentDiv(Secondary.Select(x => x.Render(context)))
- };
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControl[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControl item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControl[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControl item)
+ {
+ _secondary.Remove(item);
+ }
- return new HtmlElementTextContentDiv(elements)
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var footerCtrl = (preferences.Any() || primary.Any() || secondary.Any()) ? new ControlPanelFooter
+ (
+ Id,
+ new ControlPanel(null, [.. preferences]),
+ new ControlPanel(null, [.. primary]),
+ new ControlPanel(null, [.. secondary])
+ )
{
- Id = Id,
- Class = Css.Concatenate("footer", GetClasses()),
- Style = Style.Concatenate("", GetStyles()),
- Role = Role
- };
+ Classes = ["wx-footer"],
+ } : null;
+
+ return footerCtrl?.Render(renderContext, visualTree);
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeader.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeader.cs
index b2b7d24..354c807 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeader.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeader.cs
@@ -1,8 +1,7 @@
using System.Collections.Generic;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -41,21 +40,21 @@ public virtual TypeSticky Sticky
///
/// Returns or sets the application navigator.
///
- public ControlWebAppHeaderAppNavigator AppNavigator { get; } = new ControlWebAppHeaderAppNavigator("webexpress.webapp.header.appnavigator")
+ public ControlWebAppHeaderAppNavigator AppNavigator { get; } = new ControlWebAppHeaderAppNavigator("wx-header-appnavigator")
{
};
///
/// Returns or setss the name of the application.
///
- public ControlWebAppHeaderAppTitle AppTitle { get; } = new ControlWebAppHeaderAppTitle("webexpress.webapp.header.apptitle")
+ public ControlWebAppHeaderAppTitle AppTitle { get; } = new ControlWebAppHeaderAppTitle("wx-header-apptitle")
{
};
///
/// Returns or sets the navigation of the application.
///
- public ControlWebAppHeaderAppNavigation AppNavigation { get; } = new ControlWebAppHeaderAppNavigation("webexpress.webapp.header.appnavigation")
+ public ControlWebAppHeaderAppNavigation AppNavigation { get; } = new ControlWebAppHeaderAppNavigation("wx-header-appnavigation")
{
Layout = TypeLayoutFlexbox.Inline,
Justify = TypeJustifiedFlexbox.Start
@@ -64,60 +63,61 @@ public virtual TypeSticky Sticky
///
/// Returns or sets the quick create.
///
- public ControlWebAppHeaderQuickCreate QuickCreate { get; } = new ControlWebAppHeaderQuickCreate("webexpress.webapp.header.quickcreate")
+ public ControlWebAppHeaderQuickCreate QuickCreate { get; } = new ControlWebAppHeaderQuickCreate("wx-header-quickcreate")
{
};
///
/// Returns or sets the navigation of the application helpers.
///
- public ControlWebAppHeaderHelp Help { get; } = new ControlWebAppHeaderHelp("webexpress.webapp.header.help")
+ public ControlWebAppHeaderHelp Help { get; } = new ControlWebAppHeaderHelp("wx-header-help")
{
};
///
- /// Returns or sets the navigation of the application settings.
+ /// Returns or sets the navigation of the application helpers.
///
- public ControlWebAppHeaderSettings Settings { get; } = new ControlWebAppHeaderSettings("webexpress.webapp.header.settings")
+ public ControlWebAppHeaderNotification Notifications { get; } = new ControlWebAppHeaderNotification("wx-header-notifications")
{
};
///
- /// Constructor
+ /// Returns or sets the navigation of the application settings.
///
- /// The control id.
- public ControlWebAppHeader(string id = null)
- : base(id)
+ public ControlWebAppHeaderSettings Settings { get; } = new ControlWebAppHeaderSettings("wx-header-settings")
{
- Init();
- }
+ };
///
- /// Initialization
+ /// Initializes a new instance of the class.
///
- private void Init()
+ /// The control id.
+ public ControlWebAppHeader(string id = null)
+ : base(id)
{
Fixed = TypeFixed.Top;
- Styles = new List(new[] { "position: sticky; top: 0; z-index: 99;" });
+ Styles = new List(["position: sticky; top: 0; z-index: 99;"]);
Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
- BackgroundColor = LayoutSchema.HeaderBackground;
}
///
- /// Convert to html.
+ /// Converts the control to an HTML representation.
///
- /// 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 visual tree representing the control's structure.
+ /// An HTML node representing the rendered control.
+ public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree)
{
var content = new ControlPanelFlexbox
(
+ null,
AppNavigator,
AppTitle,
AppNavigation,
QuickCreate,
new ControlPanel() { Margin = new PropertySpacingMargin(PropertySpacing.Space.Auto, PropertySpacing.Space.None) },
Help,
+ Notifications,
Settings
)
{
@@ -125,7 +125,7 @@ public override IHtmlNode Render(RenderContext context)
Align = TypeAlignFlexbox.Center
};
- return new HtmlElementSectionHeader(content.Render(context))
+ return new HtmlElementSectionHeader(content.Render(renderContext, visualTree))
{
Id = Id,
Class = Css.Concatenate("navbar", GetClasses()),
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigation.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigation.cs
index eb67063..e8a97fb 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigation.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigation.cs
@@ -1,82 +1,143 @@
using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
///
- /// Header for a web app.
+ /// Represents the header navigation control for the web application.
///
public class ControlWebAppHeaderAppNavigation : ControlPanelFlexbox
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppHeaderAppNavigation(string id = null)
: base(id)
{
- Init();
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlNavigationItem[] items)
{
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ _preferences.AddRange(items);
}
///
- /// Convert to html.
+ /// Removes an item from the preferences area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlNavigationItem item)
{
+ _preferences.Remove(item);
+ }
- var preferences = new ControlNavigation("webexpress.webapp.header.appnavigation.preferences", Preferences)
- {
- Layout = TypeLayoutTab.Default,
- ActiveColor = LayoutSchema.HeaderNavigationActiveBackground,
- ActiveTextColor = LayoutSchema.HeaderNavigationActive,
- LinkColor = LayoutSchema.HeaderNavigationLink
- };
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlNavigationItem[] items)
+ {
+ _primary.AddRange(items);
+ }
- var primary = new ControlNavigation("webexpress.webapp.header.appnavigation.primary", Primary)
- {
- Layout = TypeLayoutTab.Default,
- ActiveColor = LayoutSchema.HeaderNavigationActiveBackground,
- ActiveTextColor = LayoutSchema.HeaderNavigationActive,
- LinkColor = LayoutSchema.HeaderNavigationLink
- };
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlNavigationItem item)
+ {
+ _primary.Remove(item);
+ }
- var secondary = new ControlNavigation("webexpress.webapp.header.appnavigation.secondary", Secondary)
- {
- Layout = TypeLayoutTab.Default,
- ActiveColor = LayoutSchema.HeaderNavigationActiveBackground,
- ActiveTextColor = LayoutSchema.HeaderNavigationActive,
- LinkColor = LayoutSchema.HeaderNavigationLink
- };
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlNavigationItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlNavigationItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ );
- return new HtmlElementTextContentDiv(preferences.Render(context), primary.Render(context), secondary.Render(context))
+ return new HtmlElementTextContentDiv
+ (
+ preferences.Any() ? new ControlNavigation("webexpress.webapp.header.appnavigation.preferences", [.. preferences])
+ {
+ Layout = TypeLayoutTab.Default,
+ }.Render(renderContext, visualTree) : null,
+ primary.Any() ? new ControlNavigation("webexpress.webapp.header.appnavigation.primary", [.. primary])
+ {
+ Layout = TypeLayoutTab.Default,
+ }.Render(renderContext, visualTree) : null,
+ secondary.Any() ? new ControlNavigation("webexpress.webapp.header.appnavigation.secondary", Secondary.Union(secondary).ToArray())
+ {
+ Layout = TypeLayoutTab.Default,
+ }.Render(renderContext, visualTree) : null
+ )
{
Id = Id,
Class = Css.Concatenate("", GetClasses()),
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigator.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigator.cs
index ee607d9..bd3a218 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigator.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppNavigator.cs
@@ -1,9 +1,12 @@
using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.Internationalization;
-using WebExpress.WebCore.WebComponent;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -12,79 +15,175 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppHeaderAppNavigator : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppHeaderAppNavigator(string id = null)
: base(id)
{
- Init();
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
{
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ _preferences.AddRange(items);
}
///
- /// Convert to html.
+ /// Removes an item from the preferences area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
{
- var application = ComponentManager.ApplicationManager.GetApplcation(context.Page.ApplicationContext?.ApplicationId);
+ _preferences.Remove(item);
+ }
- var hamburger = new List
- {
- new ControlDropdownItemHeader() { Text = context.I18N(context.Page.ApplicationContext, context.Page.ApplicationContext?.ApplicationName) }
- };
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
+ {
+ _primary.AddRange(items);
+ }
- hamburger.AddRange(Primary);
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
- if (Primary.Count > 0 && Secondary.Count > 0)
- {
- hamburger.Add(new ControlDropdownItemDivider());
- }
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
- hamburger.AddRange(Secondary);
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var application = renderContext?.PageContext?.ApplicationContext;
+ var items = GetItems(renderContext);
- var logo = (hamburger.Count > 1) ?
- (IControl)new ControlDropdown("webexpress.webapp.header.icon", hamburger)
+ var navigatorCtrl = items.Any() ?
+ (IControl)new ControlDropdown(Id, [.. items])
{
- Image = application?.Icon,
+ Image = application?.Icon.ToString(),
Height = 50,
Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None),
- Styles = new List() { "padding: 0.5em;" }
+ Styles = ["padding: 0.5em;"]
} :
- new ControlImage("webexpress.webapp.header.icon")
+ new ControlImage(Id)
{
- Uri = application?.Icon,
+ Uri = application?.Icon.ToUri(),
Height = 50,
Padding = new PropertySpacingPadding(PropertySpacing.Space.Two),
Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None)
};
- return logo?.Render(context);
+ return navigatorCtrl?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var application = renderContext?.PageContext?.ApplicationContext;
+
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (preferences.Any() && primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, application?.ApplicationName));
+ }
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if (primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppTitle.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppTitle.cs
index 0afba02..790662e 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppTitle.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderAppTitle.cs
@@ -1,8 +1,7 @@
using WebExpress.WebCore.Internationalization;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -12,43 +11,35 @@ namespace WebExpress.WebApp.WebControl
public class ControlWebAppHeaderAppTitle : ControlLink
{
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppHeaderAppTitle(string id = null)
: base(id)
- {
- Init();
- }
-
- ///
- /// Initialization
- ///
- private void Init()
{
Decoration = TypeTextDecoration.None;
}
///
- /// Convert to html.
+ /// Converts the control to an HTML representation.
///
- /// 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 visual tree representing the control's structure.
+ /// An HTML node representing the rendered control.
+ public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree)
{
var apptitle = new ControlText()
{
- Text = context.I18N(context.ApplicationContext, context.ApplicationContext?.ApplicationName),
- TextColor = LayoutSchema.HeaderTitle,
+ Text = I18N.Translate(renderContext.Request.Culture, renderContext.PageContext?.ApplicationContext?.ApplicationName),
Format = TypeFormatText.H1,
Padding = new PropertySpacingPadding(PropertySpacing.Space.One),
Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.Null)
};
- return new HtmlElementTextSemanticsA(apptitle.Render(context))
+ return new HtmlElementTextSemanticsA(apptitle.Render(renderContext, visualTree))
{
Id = Id,
- Href = context?.Page?.ApplicationContext?.ContextPath?.ToString(),
+ Href = renderContext?.PageContext?.ApplicationContext?.ContextPath?.ToString(),
Class = Css.Concatenate("", GetClasses()),
Style = Style.Concatenate("", GetStyles()),
Role = Role
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderHelp.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderHelp.cs
index 356e244..896dcb2 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderHelp.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderHelp.cs
@@ -1,8 +1,13 @@
using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.Internationalization;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -11,76 +16,166 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppHeaderHelp : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The controls id.
public ControlWebAppHeaderHelp(string id = null)
: base(id)
{
- Init();
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
{
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
+ {
+ _preferences.Remove(item);
}
///
- /// Convert to html.
+ /// Adds items to the primary area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
{
- var helpList = new List
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ var helpCtlr = items.Any() ?
+ new ControlDropdown(Id, [.. items])
+ {
+ Icon = new IconInfoCircle(),
+ AlignmentMenu = TypeAlignmentDropdownMenu.Right,
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return helpCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (preferences.Any() && primary.Any() && secondary.Any())
{
- new ControlDropdownItemHeader() { Text = context.I18N("webexpress.webapp", "header.help.label") }
- };
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, "webexpress.webapp:header.help.label"));
+ }
- helpList.AddRange(Preferences);
- if (Preferences.Count > 0 && Primary.Count > 0)
+ foreach (var item in preferences)
{
- helpList.Add(new ControlDropdownItemDivider());
+ yield return item;
}
- helpList.AddRange(Primary);
- if (Primary.Count > 0 && Secondary.Count > 0)
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
{
- helpList.Add(new ControlDropdownItemDivider());
+ yield return new ControlDropdownItemDivider();
}
- helpList.AddRange(Secondary);
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
- var help = (helpList.Count > 1) ?
- new ControlDropdown(Id, helpList)
+ if (primary.Any() && secondary.Any())
{
- Icon = new PropertyIcon(TypeIcon.InfoCircle),
- AlignmentMenu = TypeAlignmentDropdownMenu.Right,
- BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
- } :
- null;
+ yield return new ControlDropdownItemDivider();
+ }
- return help?.Render(context);
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderNotification.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderNotification.cs
new file mode 100644
index 0000000..01e4e78
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderNotification.cs
@@ -0,0 +1,181 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a control for displaying header notifications in the web application.
+ ///
+ public class ControlWebAppHeaderNotification : Control
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The controls id.
+ public ControlWebAppHeaderNotification(string id = null)
+ : base(id)
+ {
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ var helpCtlr = items.Any() ?
+ new ControlDropdown(Id, [.. items])
+ {
+ Icon = new IconInfoCircle(),
+ AlignmentMenu = TypeAlignmentDropdownMenu.Right,
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return helpCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (preferences.Any() && primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, "webexpress.webapp:header.notification.label"));
+ }
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if (primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderQuickCreate.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderQuickCreate.cs
index 887564b..b63157d 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderQuickCreate.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderQuickCreate.cs
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.Internationalization;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -13,78 +15,142 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppHeaderQuickCreate : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppHeaderQuickCreate(string id = null)
: base(id)
{
- Init();
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlSplitButtonItem[] items)
{
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlSplitButtonItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlSplitButtonItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlSplitButtonItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlSplitButtonItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlSplitButtonItem item)
+ {
+ _secondary.Remove(item);
}
///
- /// Convert to html.
+ /// Converts the control to an HTML representation.
///
- /// 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 visual tree representing the control's structure.
+ /// An HTML node representing the rendered control.
+ public override IHtmlNode Render(IRenderControlContext renderContext, IVisualTreeControl visualTree)
{
- var quickcreateList = new List(Preferences);
- quickcreateList.AddRange(Primary);
- quickcreateList.AddRange(Secondary);
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
- var firstQuickcreate = (quickcreateList.FirstOrDefault() as ControlLink);
- firstQuickcreate?.Render(context);
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
- var quickcreate = (quickcreateList.Count > 1) ?
- (IControl)new ControlSplitButtonLink(Id, quickcreateList.Skip(1))
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var quickcreateList = preferences
+ .Union(primary)
+ .Union(secondary);
+
+ var firstQuickcreate = quickcreateList.FirstOrDefault() as ControlSplitButtonItemLink;
+ var nextQuickcreate = quickcreateList.Skip(1);
+
+ var quickcreate = nextQuickcreate.Any() ?
+ (IControl)new ControlSplitButtonLink(Id, nextQuickcreate.Skip(1).ToArray())
{
- Text = context.I18N("webexpress.webapp", "header.quickcreate.label"),
+ Text = I18N.Translate(renderContext.Request?.Culture, "webexpress.webapp:header.quickcreate.label"),
Uri = firstQuickcreate?.Uri,
- BackgroundColor = LayoutSchema.HeaderQuickCreateButtonBackground,
- Size = LayoutSchema.HeaderQuickCreateButtonSize,
Margin = new PropertySpacingMargin(PropertySpacing.Space.Auto, PropertySpacing.Space.None),
OnClick = firstQuickcreate?.OnClick,
Modal = firstQuickcreate?.Modal
} :
- (Preferences.Count > 0) ?
+ Preferences.Any() ?
new ControlButtonLink(Id)
{
- Text = context.I18N("webexpress.webapp", "header.quickcreate.label"),
+ Text = I18N.Translate(renderContext.Request?.Culture, "webexpress.webapp:header.quickcreate.label"),
Uri = firstQuickcreate?.Uri,
- BackgroundColor = LayoutSchema.HeaderQuickCreateButtonBackground,
- Size = LayoutSchema.HeaderQuickCreateButtonSize,
- Margin = new PropertySpacingMargin(PropertySpacing.Space.Auto, PropertySpacing.Space.None),
OnClick = firstQuickcreate?.OnClick,
Modal = firstQuickcreate?.Modal
} :
null;
- return quickcreate?.Render(context);
+ return quickcreate?.Render(renderContext, visualTree);
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderSettings.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderSettings.cs
index d56dcf3..1b646a2 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderSettings.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeaderSettings.cs
@@ -1,8 +1,14 @@
using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.Internationalization;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
+using WebExpress.WebCore.WebSettingPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -11,76 +17,217 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppHeaderSettings : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppHeaderSettings(string id = null)
: base(id)
{
- Init();
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
{
- Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ _preferences.AddRange(items);
}
///
- /// Convert to html.
+ /// Removes an item from the preferences area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
{
- var settingsList = new List
- {
- new ControlDropdownItemHeader() { Text = context.I18N("webexpress.webapp", "header.setting.label") }
- };
+ _preferences.Remove(item);
+ }
- settingsList.AddRange(Preferences);
- if (Preferences.Count > 0 && Primary.Count > 0)
- {
- settingsList.Add(new ControlDropdownItemDivider());
- }
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
+ {
+ _primary.AddRange(items);
+ }
- settingsList.AddRange(Primary);
- if (Primary.Count > 0 && Secondary.Count > 0)
- {
- settingsList.Add(new ControlDropdownItemDivider());
- }
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
- settingsList.AddRange(Secondary);
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
- var settings = (settingsList.Count > 1) ?
- new ControlDropdown(Id, settingsList)
+ var settingCtlr = items.Any() ?
+ new ControlDropdown(Id, [.. items])
{
- Icon = new PropertyIcon(TypeIcon.Cog),
+ Icon = new IconCog(),
AlignmentMenu = TypeAlignmentDropdownMenu.Right,
BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
} :
null;
- return settings?.Render(context);
+ return settingCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var settinPageManager = WebEx.ComponentHub.SettingPageManager;
+ var appicationContext = renderContext.PageContext?.ApplicationContext;
+ var preferenceCategories = settinPageManager?.GetSettingCategories(appicationContext)
+ .Where(x => x.Section == SettingSection.Preferences)
+ .Select
+ (
+ x => new ControlDropdownItemLink()
+ {
+ Text = I18N.Translate(renderContext, x?.Name),
+ Uri = settinPageManager.GetFirstSettingPage(appicationContext, x)?.Route.ToUri(),
+ Icon = x.Icon
+ }
+ );
+ var primaryCategories = settinPageManager?.GetSettingCategories(appicationContext)
+ .Where(x => x.Section == SettingSection.Primary)
+ .Select
+ (
+ x => new ControlDropdownItemLink()
+ {
+ Text = I18N.Translate(renderContext, x?.Name),
+ Uri = settinPageManager.GetFirstSettingPage(appicationContext, x)?.Route.ToUri(),
+ Icon = x.Icon
+ }
+ );
+ var secondaryCategories = settinPageManager?.GetSettingCategories(appicationContext)
+ .Where(x => x.Section == SettingSection.Secondary)
+ .Select
+ (
+ x => new ControlDropdownItemLink()
+ {
+ Text = I18N.Translate(renderContext, x?.Name),
+ Uri = settinPageManager.GetFirstSettingPage(appicationContext, x)?.Route.ToUri(),
+ Icon = x.Icon
+ }
+ );
+
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (preferences.Any() || primary.Any() || secondary.Any() || preferenceCategories.Any())
+ {
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, "webexpress.webapp:header.setting.label"));
+ }
+
+ foreach (var item in preferenceCategories)
+ {
+ yield return item;
+ }
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if ((preferenceCategories.Any() || preferences.Any()) && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in primaryCategories)
+ {
+ yield return item;
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if ((primaryCategories.Any() || primary.Any()) && secondary.Any())
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in secondaryCategories)
+ {
+ yield return item;
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeadline.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeadline.cs
index b397489..cd651b5 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppHeadline.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeadline.cs
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
-using static WebExpress.WebCore.Internationalization.InternationalizationManager;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
@@ -13,147 +15,232 @@ namespace WebExpress.WebApp.WebControl
///
public class ControlWebAppHeadline : Control
{
+ private readonly List _prologue = [];
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+ private readonly List _metadata = [];
+
///
- /// Returns or sets the prologue area.
+ /// Returns the prologue area.
///
- public List Prologue { get; protected set; } = new List();
+ public IEnumerable Prologue => _prologue;
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Returns or sets the preferences area for the more control.
+ /// Returns the secondary area for the metadata.
///
- public List MorePreferences { get; protected set; } = new List();
+ public IEnumerable Metadata => _metadata;
///
- /// Returns or sets the primary area for the more control.
+ /// Returns the more control.
///
- public List MorePrimary { get; protected set; } = new List();
+ public ControlWebAppHeadlineMore More { get; } = new ControlWebAppHeadlineMore("wx-content-main-headline-more")
+ {
+ };
///
- /// Returns or sets the secondary area for the more control.
+ /// Initializes a new instance of the class.
///
- public List MoreSecondary { get; protected set; } = new List();
+ /// The control id.
+ public ControlWebAppHeadline(string id = null)
+ : base(id)
+ {
+ }
///
- /// Returns or sets the secondary area for the metadata.
+ /// Adds items to the prologue area.
///
- public List Metadata { get; protected set; } = new List();
+ /// The items to add to the prologue area.
+ public void AddPrologue(params IControlToolbarItem[] items)
+ {
+ _prologue.AddRange(items);
+ }
///
- /// Constructor
+ /// Removes an item from the prologue area.
///
- /// The control id.
- public ControlWebAppHeadline(string id = null)
- : base(id)
+ /// The item to remove from the prologue area.
+ public void RemovePrologue(IControlToolbarItem item)
{
- Init();
+ _prologue.Remove(item);
}
///
- /// Initialization
+ /// Adds items to the preferences area.
///
- private void Init()
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlToolbarItem[] items)
{
- BackgroundColor = LayoutSchema.HeadlineBackground;
+ _preferences.AddRange(items);
}
///
- /// Convert to html.
+ /// Removes an item from the preferences area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlToolbarItem item)
{
- var prologue = new ControlPanelFlexbox(Prologue) { Layout = TypeLayoutFlexbox.Default, Align = TypeAlignFlexbox.Center, Justify = TypeJustifiedFlexbox.Start };
- prologue.Content.Add(new ControlText()
- {
- Text = I18N(context.Culture, context.Page.Title),
- TextColor = LayoutSchema.HeadlineTitle,
- Format = TypeFormatText.H2,
- Padding = new PropertySpacingPadding(PropertySpacing.Space.One),
- Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.Null)
- });
- prologue.Content.AddRange(Preferences);
-
- var epilog = new ControlPanelFlexbox(Secondary) { Layout = TypeLayoutFlexbox.Default, Align = TypeAlignFlexbox.Center, Justify = TypeJustifiedFlexbox.End };
- if (MorePreferences.Count() > 0 || MorePrimary.Count() > 0 || MoreSecondary.Count() > 0)
- {
- var more = new ControlDropdown("more")
- {
- Title = I18N(context.Culture, "webexpress.webapp", "headline.more.title"),
- Icon = new PropertyIcon(TypeIcon.EllipsisHorizontal),
- TextColor = LayoutSchema.HeadlineTitle,
- Padding = new PropertySpacingPadding(PropertySpacing.Space.One),
- Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.Null)
- };
-
- foreach (var v in MorePreferences)
- {
- more.Add(v);
- }
+ _preferences.Remove(item);
+ }
- if (MorePreferences.Count > 0 && (MorePrimary.Count > 0 || MoreSecondary.Count > 0))
- {
- more.AddSeperator();
- }
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlToolbarItem[] items)
+ {
+ _primary.AddRange(items);
+ }
- foreach (var v in MorePrimary)
- {
- more.Add(v);
- }
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlToolbarItem item)
+ {
+ _primary.Remove(item);
+ }
- if (MorePrimary.Count() > 0 && MoreSecondary.Count > 0)
- {
- more.AddSeperator();
- }
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlToolbarItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
- foreach (var v in MoreSecondary)
- {
- more.Add(v);
- }
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlToolbarItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the metadata area.
+ ///
+ /// The items to add to the metadata area.
+ public void AddMetadata(params IControlToolbarItem[] items)
+ {
+ _metadata.AddRange(items);
+ }
- epilog.Content.Add(more);
- }
+ ///
+ /// Removes an item from the metadata area.
+ ///
+ /// The item to remove from the metadata area.
+ public void RemoveMetadata(IControlToolbarItem item)
+ {
+ _metadata.Remove(item);
+ }
- var content = new ControlPanelFlexbox
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var prologue = Prologue.Union(WebEx.ComponentHub.FragmentManager.GetFragments
(
- prologue,
- new ControlPanelFlexbox(Primary) { Layout = TypeLayoutFlexbox.Default, Align = TypeAlignFlexbox.Center, Justify = TypeJustifiedFlexbox.End },
- epilog
- )
- {
- Layout = TypeLayoutFlexbox.Default,
- Align = TypeAlignFlexbox.Center,
- Justify = TypeJustifiedFlexbox.Between
- };
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
- var metadata = new HtmlElementTextContentDiv
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
(
- Metadata.Select(x => x.Render(context))
- )
- {
- Class = Css.Concatenate("ms-2 me-2 mb-3 text-secondary"),
- Style = Style.Concatenate("font-size:0.75rem;")
- };
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var metadata = Metadata.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
return new HtmlElementSectionHeader
(
- content.Render(context),
- Metadata.Count > 0 ? metadata : null
+ new ControlPanelFlexbox
+ (
+ null,
+ prologue.Any() ? new ControlPanelFlexbox(null, [.. prologue])
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Center,
+ Justify = TypeJustifiedFlexbox.Start
+ } : null,
+ new ControlText()
+ {
+ Text = I18N.Translate(renderContext.Request?.Culture, renderContext.PageContext?.PageTitle),
+ Format = TypeFormatText.H2,
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.One),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.None, PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.Null)
+ },
+ preferences.Any() ? new ControlPanelFlexbox(null, [.. preferences])
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Center,
+ Justify = TypeJustifiedFlexbox.Start
+ } : null,
+ primary.Any() ? new ControlPanelFlexbox(null, [.. primary])
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Center,
+ Justify = TypeJustifiedFlexbox.Start
+ } : null,
+ secondary.Any() ? new ControlPanelFlexbox(null, [.. secondary])
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Center,
+ Justify = TypeJustifiedFlexbox.End
+ } : null,
+ More
+ )
+ {
+ Layout = TypeLayoutFlexbox.Default,
+ Align = TypeAlignFlexbox.Center,
+ Justify = TypeJustifiedFlexbox.Between
+ }.Render(renderContext, visualTree),
+ metadata.Any() ? new HtmlElementTextContentDiv
+ (
+ metadata.Select(x => x.Render(renderContext, visualTree)).ToArray()
+ )
+ {
+ Class = Css.Concatenate("ms-2 me-2 mb-3 text-secondary"),
+ Style = Style.Concatenate("font-size:0.75rem;")
+ } : null
)
{
Id = Id,
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppHeadlineMore.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppHeadlineMore.cs
new file mode 100644
index 0000000..647b367
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppHeadlineMore.cs
@@ -0,0 +1,181 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a headline control with more options in the web application.
+ ///
+ public class ControlWebAppHeadlineMore : Control
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppHeadlineMore(string id = null)
+ : base(id)
+ {
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ var settingsCtlr = items.Any() ?
+ new ControlDropdown(Id, [.. items])
+ {
+ Icon = new IconEllipsisHorizontal(),
+ AlignmentMenu = TypeAlignmentDropdownMenu.Right,
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return settingsCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (preferences.Any() && primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, "webexpress.webapp:headline.more.title"));
+ }
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if (primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppMain.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppMain.cs
new file mode 100644
index 0000000..4760120
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppMain.cs
@@ -0,0 +1,164 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents the main control panel for the web application.
+ ///
+ public class ControlWebAppMain : Control
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Returns the page properties.
+ ///
+ public ControlWebAppProperty Property { get; } = new ControlWebAppProperty("wx-content-main-property");
+
+ ///
+ /// Returns the headline control.
+ ///
+ public ControlWebAppHeadline Headline { get; } = new ControlWebAppHeadline("wx-content-main-headline");
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppMain(string id = null)
+ : base(id)
+ {
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControl[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControl item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControl[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControl item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControl[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControl item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var mainCtlr = new ControlPanelMain
+ (
+ Id,
+ new ControlPanel
+ (
+ null,
+ new ControlPanel
+ (
+ null,
+ Headline,
+ new ControlPanel(null, [.. preferences]),
+ new ControlPanel(null, [.. primary]),
+ new ControlPanel(null, [.. secondary])
+ )
+ {
+ },
+ Property
+ )
+ {
+ }
+ )
+ {
+ BackgroundColor = BackgroundColor,
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ };
+
+ return mainCtlr?.Render(renderContext, visualTree);
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppProperty.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppProperty.cs
index 46d6645..5049e6e 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppProperty.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppProperty.cs
@@ -1,73 +1,148 @@
using System.Collections.Generic;
using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
///
- /// Properties for a web app.
+ /// Represents a control for managing web application properties, including preferences, primary, and secondary areas.
///
public class ControlWebAppProperty : Control
{
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
///
- /// Returns or sets the preferences area.
+ /// Returns the preferences area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the primary area.
+ /// Returns the primary area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Returns or sets the secondary area.
+ /// Returns the secondary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppProperty(string id = null)
: base(id)
{
- Init();
}
///
- /// Initialization
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControl[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControl item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControl[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
///
- private void Init()
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControl item)
{
- BackgroundColor = LayoutSchema.PropertyBackground;
+ _primary.Remove(item);
}
///
- /// Convert to html.
+ /// Adds items to the secondary area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControl[] items)
{
- if (Preferences.Count == 0 && Primary.Count == 0 && Secondary.Count == 0)
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControl item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ if (!preferences.Any() && !primary.Any() && !secondary.Any())
{
return null;
}
- var preferences = new HtmlElementTextContentDiv(Preferences.Select(x => x.Render(context)));
- var primary = new HtmlElementTextContentDiv(Primary.Select(x => x.Render(context)));
- var secondary = new HtmlElementTextContentDiv(Secondary.Select(x => x.Render(context)));
-
- return new HtmlElementTextContentDiv(preferences, primary, secondary)
+ var propertyCtlr = (preferences.Any() || primary.Any() || secondary.Any()) ?
+ new ControlPanelFlexbox
+ (
+ Id,
+ new ControlPanel(null, [.. preferences]),
+ new ControlPanel(null, [.. primary]),
+ new ControlPanel(null, [.. secondary])
+ )
{
- Id = Id,
- Class = Css.Concatenate("proterty", GetClasses()),
- Style = GetStyles(),
- Role = Role
- };
+ Classes = ["proterty"],
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return propertyCtlr?.Render(renderContext, visualTree);
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppSettingMenu.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppSettingMenu.cs
new file mode 100644
index 0000000..c795fff
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppSettingMenu.cs
@@ -0,0 +1,140 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebSettingPage;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a control for the settings menu in the web application.
+ ///
+ public class ControlWebAppSettingMenu : ControlWebAppSidebar
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppSettingMenu(string id = null)
+ : base(id)
+ {
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the control.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ protected override IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var settinPageManager = WebEx.ComponentHub.SettingPageManager;
+ var appicationContext = renderContext.PageContext?.ApplicationContext;
+ var settingPageContext = renderContext.PageContext as ISettingPageContext;
+ var currentCategory = settingPageContext?.SettingGroup?.SettingCategory;
+ var groups = settinPageManager.GetSettingGroups(renderContext.PageContext?.ApplicationContext, currentCategory);
+ var controls = new List();
+
+ foreach (var group in groups.OrderBy(x => x))
+ {
+ var settingPages = settinPageManager.GetSettingPages(appicationContext, group);
+ var listCtrl = new ControlList(null) { Layout = TypeLayoutList.Flush };
+
+ controls.Add(new ControlText() { Text = group?.Name });
+ controls.Add(listCtrl);
+
+ foreach (var page in settingPages
+ .Where(x => x.Section == SettingSection.Preferences)
+ .OrderBy(x => I18N.Translate(renderContext, x.PageTitle)))
+ {
+ if (!page.Hide && (!page.Conditions.Any() || page.Conditions.All(x => x.Fulfillment(renderContext.Request))))
+ {
+ listCtrl.Add(new ControlListItemLink()
+ {
+ Text = page.PageTitle,
+ Icon = page.Icon,
+ Uri = page?.Route.ToUri(),
+ Active = page == renderContext.PageContext ? TypeActive.Active : TypeActive.None
+ });
+ }
+ }
+
+ foreach (var page in settingPages
+ .Where(x => x.Section == SettingSection.Primary)
+ .OrderBy(x => I18N.Translate(renderContext, x.PageTitle)))
+ {
+ if (!page.Hide && (!page.Conditions.Any() || page.Conditions.All(x => x.Fulfillment(renderContext.Request))))
+ {
+ listCtrl.Add(new ControlListItemLink()
+ {
+ Text = page.PageTitle,
+ Icon = page.Icon,
+ Uri = page?.Route.ToUri(),
+ Active = page == renderContext.PageContext ? TypeActive.Active : TypeActive.None
+ });
+ }
+ }
+
+ foreach (var page in settingPages
+ .Where(x => x.Section == SettingSection.Secondary)
+ .OrderBy(x => I18N.Translate(renderContext, x.PageTitle)))
+ {
+ if (!page.Hide && (!page.Conditions.Any() || page.Conditions.All(x => x.Fulfillment(renderContext.Request))))
+ {
+ listCtrl.Add(new ControlListItemLink()
+ {
+ Text = page.PageTitle,
+ Icon = page.Icon,
+ Uri = page?.Route.ToUri(),
+ Active = page == renderContext.PageContext ? TypeActive.Active : TypeActive.None
+ });
+ }
+ }
+ }
+
+ foreach (var item in Header.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var item in Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var control in controls)
+ {
+ yield return control;
+ }
+
+ foreach (var item in Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var item in Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppSettingTab.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppSettingTab.cs
new file mode 100644
index 0000000..ef263aa
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppSettingTab.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebCore.WebSettingPage;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a settings tab control in the web application.
+ ///
+ public class ControlWebAppSettingTab : Control
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppSettingTab(string id = null)
+ : base(id)
+ {
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlNavigationItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlNavigationItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlNavigationItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlNavigationItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlNavigationItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlNavigationItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ Enable = items.Count() > 1;
+
+ if (!Enable)
+ {
+ return null;
+ }
+
+ return new ControlNavigation(Id, [.. items])
+ {
+ Layout = TypeLayoutTab.Tab
+ }.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items from the preferences, primary, and secondary areas.
+ ///
+ /// The context in which the control is rendered.
+ /// A list of tab items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var settinPageManager = WebEx.ComponentHub.SettingPageManager;
+ var appicationContext = renderContext.PageContext?.ApplicationContext;
+ var settingPageContext = renderContext.PageContext as ISettingPageContext;
+ var categories = settinPageManager?.GetSettingCategories(appicationContext)
+ .Select
+ (
+ x => new ControlNavigationItemLink()
+ {
+ Text = I18N.Translate(renderContext, x?.Name),
+ Uri = settinPageManager.GetFirstSettingPage(appicationContext, x).Route.ToUri(),
+ Active = settingPageContext.SettingCategory == x ? TypeActive.Active : TypeActive.None
+ }
+ );
+
+ foreach (var item in Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var category in categories)
+ {
+ yield return category;
+ }
+
+ foreach (var item in Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var item in Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppSidebar.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppSidebar.cs
index 7edfff1..0d02a96 100644
--- a/src/WebExpress.WebApp/WebControl/ControlWebAppSidebar.cs
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppSidebar.cs
@@ -1,86 +1,189 @@
using System.Collections.Generic;
using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
using WebExpress.WebCore.WebHtml;
-using WebExpress.WebCore.WebPage;
-using WebExpress.WebApp.WebPage;
using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
namespace WebExpress.WebApp.WebControl
{
///
- /// Sidebar for a web app.
+ /// Represents a sidebar control for the web application.
///
public class ControlWebAppSidebar : Control
{
- ///
- /// Returns or sets the header area.
- ///
- public List Header { get; protected set; } = new List();
+ private readonly List _header = [];
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
///
- /// Returns or sets the preferences area.
+ /// Returns the header area.
///
- public List Preferences { get; protected set; } = new List();
+ public IEnumerable Header => _header;
///
- /// Returns or sets the primary area.
+ /// Returns the preferences area.
///
- public List Primary { get; protected set; } = new List();
+ public IEnumerable Preferences => _preferences;
///
- /// Returns or sets the secondary area.
+ /// Returns the primary area.
///
- public List Secondary { get; protected set; } = new List();
+ public IEnumerable Primary => _primary;
///
- /// Determines whether content exists
+ /// Returns the secondary area.
///
- public bool HasContent => Header.Any() || Preferences.Any() || Primary.Any() || Secondary.Any();
+ public IEnumerable Secondary => _secondary;
///
- /// Constructor
+ /// Initializes a new instance of the class.
///
/// The control id.
public ControlWebAppSidebar(string id = null)
: base(id)
{
- Init();
}
///
- /// Initialization
+ /// Adds items to the header area.
+ ///
+ /// The items to add to the header area.
+ public void AddHeader(params IControlToolbarItem[] items)
+ {
+ _header.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the header area.
+ ///
+ /// The item to remove from the header area.
+ public void RemoveHeader(IControlToolbarItem item)
+ {
+ _header.Remove(item);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlToolbarItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
///
- private void Init()
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlToolbarItem item)
{
- BackgroundColor = LayoutSchema.SidebarBackground;
- //Height = TypeHeight.OneHundred;
+ _preferences.Remove(item);
}
///
- /// Convert to html.
+ /// Adds items to the primary area.
///
- /// The context in which the control is rendered.
- /// The control as html.
- public override IHtmlNode Render(RenderContext context)
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlToolbarItem[] items)
{
- if (!HasContent)
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlToolbarItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlToolbarItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlToolbarItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ var sidebarCtlr = items.Any() ?
+ new ControlPanelFlexbox(Id, [.. items])
{
- return null;
+ Classes = ["wx-sidebar"],
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return sidebarCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the control.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ protected virtual IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ foreach (var item in Header.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
}
- var elements = new List();
- elements.AddRange(Header.Select(x => x.Render(context)));
- elements.AddRange(Preferences.Select(x => x.Render(context)));
- elements.AddRange(Primary.Select(x => x.Render(context)));
- elements.AddRange(Secondary.Select(x => x.Render(context)));
+ foreach (var item in Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
+
+ foreach (var item in Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
+ {
+ yield return item;
+ }
- return new HtmlElementTextContentDiv(elements)
+ foreach (var item in Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ )))
{
- Id = Id,
- Class = Css.Concatenate("sidebar", GetClasses()),
- Style = Style.Concatenate("display: block;", GetStyles()),
- Role = Role
- };
+ yield return item;
+ }
}
}
}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppToolbar.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppToolbar.cs
new file mode 100644
index 0000000..5e3c966
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppToolbar.cs
@@ -0,0 +1,173 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a toolbar control for a web application.
+ ///
+ public class ControlWebAppToolbar : ControlToolbar
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Returns the quick create.
+ ///
+ public ControlWebAppToolbarMore More { get; } = new ControlWebAppToolbarMore("wx-content-toolbar-more")
+ {
+ };
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppToolbar(string id = null)
+ : base(id)
+ {
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlToolbarItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlToolbarItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlToolbarItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlToolbarItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlToolbarItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlToolbarItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ Enable = items.Any();
+
+ return base.Render(renderContext, visualTree, items);
+ }
+
+ ///
+ /// Retrieves the toolbar items from the preferences, primary, and secondary areas.
+ ///
+ /// The context in which the control is rendered.
+ /// A list of toolbar items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ).Cast());
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ).Union(Items).Cast());
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ).Cast());
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlToolbarItemDivider();
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if (primary.Any() && secondary.Any())
+ {
+ yield return new ControlToolbarItemDivider();
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/ControlWebAppToolbarMore.cs b/src/WebExpress.WebApp/WebControl/ControlWebAppToolbarMore.cs
new file mode 100644
index 0000000..739e5af
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/ControlWebAppToolbarMore.cs
@@ -0,0 +1,178 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.WebApp.WebSection;
+using WebExpress.WebCore;
+using WebExpress.WebCore.Internationalization;
+using WebExpress.WebCore.WebHtml;
+using WebExpress.WebUI.WebControl;
+using WebExpress.WebUI.WebFragment;
+using WebExpress.WebUI.WebIcon;
+using WebExpress.WebUI.WebPage;
+
+namespace WebExpress.WebApp.WebControl
+{
+ ///
+ /// Represents a toolbar control with more options in the web application.
+ ///
+ public class ControlWebAppToolbarMore : Control
+ {
+ private readonly List _preferences = [];
+ private readonly List _primary = [];
+ private readonly List _secondary = [];
+
+ ///
+ /// Returns the preferences area.
+ ///
+ public IEnumerable Preferences => _preferences;
+
+ ///
+ /// Returns the primary area.
+ ///
+ public IEnumerable Primary => _primary;
+
+ ///
+ /// Returns the secondary area.
+ ///
+ public IEnumerable Secondary => _secondary;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The control id.
+ public ControlWebAppToolbarMore(string id = null)
+ : base(id)
+ {
+ Padding = new PropertySpacingPadding(PropertySpacing.Space.Null);
+ }
+
+ ///
+ /// Adds items to the preferences area.
+ ///
+ /// The items to add to the preferences area.
+ public void AddPreferences(params IControlDropdownItem[] items)
+ {
+ _preferences.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the preferences area.
+ ///
+ /// The item to remove from the preferences area.
+ public void RemovePreference(IControlDropdownItem item)
+ {
+ _preferences.Remove(item);
+ }
+
+ ///
+ /// Adds items to the primary area.
+ ///
+ /// The items to add to the primary area.
+ public void AddPrimary(params IControlDropdownItem[] items)
+ {
+ _primary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the primary area.
+ ///
+ /// The item to remove from the primary area.
+ public void RemovePrimary(IControlDropdownItem item)
+ {
+ _primary.Remove(item);
+ }
+
+ ///
+ /// Adds items to the secondary area.
+ ///
+ /// The items to add to the secondary area.
+ public void AddSecondary(params IControlDropdownItem[] items)
+ {
+ _secondary.AddRange(items);
+ }
+
+ ///
+ /// Removes an item from the secondary area.
+ ///
+ /// The item to remove from the secondary area.
+ public void RemoveSecondary(IControlDropdownItem item)
+ {
+ _secondary.Remove(item);
+ }
+
+ ///
+ /// Converts the control to an HTML representation.
+ ///
+ /// 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, IVisualTreeControl visualTree)
+ {
+ var items = GetItems(renderContext);
+
+ var settingsCtlr = items.Any() ?
+ new ControlDropdown(Id, [.. items])
+ {
+ Icon = new IconEllipsisHorizontal(),
+ AlignmentMenu = TypeAlignmentDropdownMenu.Right,
+ //BackgroundColor = new PropertyColorButton(TypeColorButton.Dark),
+ Margin = new PropertySpacingMargin(PropertySpacing.Space.Two, PropertySpacing.Space.None, PropertySpacing.Space.None, PropertySpacing.Space.None)
+ } :
+ null;
+
+ return settingsCtlr?.Render(renderContext, visualTree);
+ }
+
+ ///
+ /// Retrieves the items to be displayed in the dropdown.
+ ///
+ /// The context in which the control is rendered.
+ /// A collection of dropdown items.
+ private IEnumerable GetItems(IRenderControlContext renderContext)
+ {
+ var preferences = Preferences.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var primary = Primary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ var secondary = Secondary.Union(WebEx.ComponentHub.FragmentManager.GetFragments
+ (
+ renderContext?.PageContext?.ApplicationContext,
+ renderContext?.PageContext?.Scopes
+ ));
+
+ yield return new ControlDropdownItemHeader(I18N.Translate(renderContext.Request, "webexpress.webapp:toolbar.more.title"));
+
+ foreach (var item in preferences)
+ {
+ yield return item;
+ }
+
+ if (preferences.Any() && (primary.Any() || secondary.Any()))
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in primary)
+ {
+ yield return item;
+ }
+
+ if (primary.Any() && secondary.Any())
+ {
+ yield return new ControlDropdownItemDivider();
+ }
+
+ foreach (var item in secondary)
+ {
+ yield return item;
+ }
+ }
+ }
+}
diff --git a/src/WebExpress.WebApp/WebControl/FormUploadEventArgs.cs b/src/WebExpress.WebApp/WebControl/FormUploadEventArgs.cs
new file mode 100644
index 0000000..20087c4
--- /dev/null
+++ b/src/WebExpress.WebApp/WebControl/FormUploadEventArgs.cs
@@ -0,0 +1,22 @@
+//using WebExpress.WebCore.WebMessage;
+//using WebExpress.WebUI.WebControl;
+
+//namespace WebExpress.WebApp.WebControl
+//{
+// public class FormUploadEventArgs : FormEventArgs
+// {
+// ///