) {
+ const claim: Claim = claims.find(item => item.type === type);
+ return claim === undefined ? "" : claim.value;
+ }
+
+}
diff --git a/Forge.Yoda.Apps.Web.React/ClientApp/src/index.css b/Forge.Yoda.Apps.Web.React/ClientApp/src/index.css
new file mode 100644
index 0000000..3365c0f
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/ClientApp/src/index.css
@@ -0,0 +1,39 @@
+html,
+body {
+ min-height: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+}
+
+/* width */
+::-webkit-scrollbar {
+ width: 5px;
+ height: 5px;
+}
+
+/* Track */
+::-webkit-scrollbar-track {
+ /*box-shadow: inset 0 0 5px grey;*/
+ border-radius: 10px;
+}
+
+/* Handle */
+::-webkit-scrollbar-thumb {
+ background: grey;
+ border-radius: 10px;
+}
+
+/* Handle on hover */
+ ::-webkit-scrollbar-thumb:hover {
+ background: #727272;
+}
+
+.height100 {
+ height: 100%;
+}
+
+.maxWidthContainer {
+ min-width: 100%;
+ width: 100%;
+}
diff --git a/Forge.Yoda.Apps.Web.React/ClientApp/src/index.js b/Forge.Yoda.Apps.Web.React/ClientApp/src/index.js
new file mode 100644
index 0000000..f4dc1e0
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/ClientApp/src/index.js
@@ -0,0 +1,17 @@
+import 'bootstrap/dist/css/bootstrap.css';
+import 'bootstrap/dist/js/bootstrap.min.js'
+
+import { createRoot } from 'react-dom/client';
+import { BrowserRouter } from 'react-router-dom';
+import App from './App';
+
+import './index.css';
+
+const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
+const rootElement = document.getElementById('root');
+const root = createRoot(rootElement);
+
+root.render(
+
+
+ );
diff --git a/Forge.Yoda.Apps.Web.React/ClientApp/src/react-app-env.d.ts b/Forge.Yoda.Apps.Web.React/ClientApp/src/react-app-env.d.ts
new file mode 100644
index 0000000..6431bc5
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/ClientApp/src/react-app-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/Forge.Yoda.Apps.Web.React/ClientApp/src/setupTests.ts b/Forge.Yoda.Apps.Web.React/ClientApp/src/setupTests.ts
new file mode 100644
index 0000000..8f2609b
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/ClientApp/src/setupTests.ts
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom';
diff --git a/Forge.Yoda.Apps.Web.React/ClientApp/tsconfig.json b/Forge.Yoda.Apps.Web.React/ClientApp/tsconfig.json
new file mode 100644
index 0000000..b8281c4
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/ClientApp/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "ES5",
+ "lib": [
+ "DOM",
+ "DOM.Iterable",
+ "ESNext",
+ "ESNext.Promise"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "strictNullChecks": false,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ },
+ "include": [
+ "src"
+ ]
+}
\ No newline at end of file
diff --git a/Forge.Yoda.Apps.Web.React/Forge.Yoda.Apps.Web.React.csproj b/Forge.Yoda.Apps.Web.React/Forge.Yoda.Apps.Web.React.csproj
new file mode 100644
index 0000000..7cae655
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Forge.Yoda.Apps.Web.React.csproj
@@ -0,0 +1,56 @@
+
+
+
+ net6.0
+ enable
+ true
+ Latest
+ false
+ ClientApp\
+ $(DefaultItemExcludes);$(SpaRoot)node_modules\**
+ https://localhost:44445
+ npm start
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wwwroot\%(RecursiveDir)%(FileName)%(Extension)
+ PreserveNewest
+ true
+
+
+
+
diff --git a/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml b/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml
new file mode 100644
index 0000000..6f92b95
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml
@@ -0,0 +1,26 @@
+@page
+@model ErrorModel
+@{
+ ViewData["Title"] = "Error";
+}
+
+Error.
+An error occurred while processing your request.
+
+@if (Model.ShowRequestId)
+{
+
+ Request ID: @Model.RequestId
+
+}
+
+Development Mode
+
+ Swapping to the Development environment displays detailed information about the error that occurred.
+
+
+ The Development environment shouldn't be enabled for deployed applications.
+ It can result in displaying sensitive information from exceptions to end users.
+ For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
+ and restarting the app.
+
diff --git a/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml.cs b/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml.cs
new file mode 100644
index 0000000..d89eb0b
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Pages/Error.cshtml.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using System.Diagnostics;
+
+namespace Forge.Yoda.Apps.Web.React.Pages
+{
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+ public class ErrorModel : PageModel
+ {
+ private readonly ILogger _logger;
+
+ public ErrorModel(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public string? RequestId { get; set; }
+
+ public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+
+ public void OnGet()
+ {
+ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Forge.Yoda.Apps.Web.React/Pages/_ViewImports.cshtml b/Forge.Yoda.Apps.Web.React/Pages/_ViewImports.cshtml
new file mode 100644
index 0000000..daf757d
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Pages/_ViewImports.cshtml
@@ -0,0 +1,3 @@
+@using Forge.Yoda.Apps.Web.React
+@namespace Forge.Yoda.Apps.Web.React.Pages
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/Forge.Yoda.Apps.Web.React/Program.cs b/Forge.Yoda.Apps.Web.React/Program.cs
new file mode 100644
index 0000000..f0265c0
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Program.cs
@@ -0,0 +1,37 @@
+
+namespace Forge.Yoda.Apps.Web.React
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ var builder = WebApplication.CreateBuilder(args);
+
+ // Add services to the container.
+
+ builder.Services.AddControllersWithViews();
+
+ var app = builder.Build();
+
+ // Configure the HTTP request pipeline.
+ if (!app.Environment.IsDevelopment())
+ {
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ }
+
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+ app.UseRouting();
+
+
+ app.MapControllerRoute(
+ name: "default",
+ pattern: "{controller}/{action=Index}/{id?}");
+
+ app.MapFallbackToFile("index.html");
+
+ app.Run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Forge.Yoda.Apps.Web.React/Properties/launchSettings.json b/Forge.Yoda.Apps.Web.React/Properties/launchSettings.json
new file mode 100644
index 0000000..b560087
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/Properties/launchSettings.json
@@ -0,0 +1,29 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:30656",
+ "sslPort": 44345
+ }
+ },
+ "profiles": {
+ "Forge.Yoda.Apps.Web.React": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7137;http://localhost:5137",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development",
+ "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
+ }
+ }
+ }
+}
diff --git a/Forge.Yoda.Apps.Web.React/appsettings.Development.json b/Forge.Yoda.Apps.Web.React/appsettings.Development.json
new file mode 100644
index 0000000..84308c9
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/appsettings.Development.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.AspNetCore.SpaProxy": "Information",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ }
+}
diff --git a/Forge.Yoda.Apps.Web.React/appsettings.json b/Forge.Yoda.Apps.Web.React/appsettings.json
new file mode 100644
index 0000000..ad75fee
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+"AllowedHosts": "*"
+}
diff --git a/Forge.Yoda.Apps.Web.React/package-lock.json b/Forge.Yoda.Apps.Web.React/package-lock.json
new file mode 100644
index 0000000..48e341a
--- /dev/null
+++ b/Forge.Yoda.Apps.Web.React/package-lock.json
@@ -0,0 +1,3 @@
+{
+ "lockfileVersion": 1
+}
diff --git a/Forge.Yoda.sln b/Forge.Yoda.sln
index f2cad31..4a4ef1f 100644
--- a/Forge.Yoda.sln
+++ b/Forge.Yoda.sln
@@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Forge.Yoda.Services.Authent
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Forge.Yoda.Externals", "Forge.Yoda.Externals\Forge.Yoda.Externals.csproj", "{EA78EA0A-D50C-456C-A7B5-ACA63D13F815}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Forge.Yoda.Apps.Web.React", "Forge.Yoda.Apps.Web.React\Forge.Yoda.Apps.Web.React.csproj", "{83FC6FFF-95D5-469A-B1F1-5CF9B35D8AB5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -82,6 +84,10 @@ Global
{EA78EA0A-D50C-456C-A7B5-ACA63D13F815}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA78EA0A-D50C-456C-A7B5-ACA63D13F815}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA78EA0A-D50C-456C-A7B5-ACA63D13F815}.Release|Any CPU.Build.0 = Release|Any CPU
+ {83FC6FFF-95D5-469A-B1F1-5CF9B35D8AB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {83FC6FFF-95D5-469A-B1F1-5CF9B35D8AB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {83FC6FFF-95D5-469A-B1F1-5CF9B35D8AB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {83FC6FFF-95D5-469A-B1F1-5CF9B35D8AB5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE