initial commit
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,5 @@
 | 
			
		||||
bin/
 | 
			
		||||
obj/
 | 
			
		||||
/packages/
 | 
			
		||||
riderModule.iml
 | 
			
		||||
/_ReSharper.Caches/
 | 
			
		||||
							
								
								
									
										15
									
								
								MyWebApp/MyWebApp.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,15 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
			
		||||
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <TargetFramework>net7.0</TargetFramework>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Include="wwwroot\assets\gumby.jpg" />
 | 
			
		||||
    <None Include="wwwroot\assets\MyWebApp.png" />
 | 
			
		||||
    <None Include="wwwroot\assets\pokey.webp" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										26
									
								
								MyWebApp/Pages/Error.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,26 @@
 | 
			
		||||
@page
 | 
			
		||||
@model ErrorModel
 | 
			
		||||
@{
 | 
			
		||||
    ViewData["Title"] = "Error";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<h1 class="text-danger">Error.</h1>
 | 
			
		||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
 | 
			
		||||
 | 
			
		||||
@if (Model.ShowRequestId)
 | 
			
		||||
{
 | 
			
		||||
    <p>
 | 
			
		||||
        <strong>Request ID:</strong> <code>@Model.RequestId</code>
 | 
			
		||||
    </p>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<h3>Development Mode</h3>
 | 
			
		||||
<p>
 | 
			
		||||
    Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
 | 
			
		||||
    It can result in displaying sensitive information from exceptions to end users.
 | 
			
		||||
    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
 | 
			
		||||
    and restarting the app.
 | 
			
		||||
</p>
 | 
			
		||||
							
								
								
									
										27
									
								
								MyWebApp/Pages/Error.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,27 @@
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
			
		||||
 | 
			
		||||
namespace MyWebApp.Pages;
 | 
			
		||||
 | 
			
		||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
 | 
			
		||||
[IgnoreAntiforgeryToken]
 | 
			
		||||
public class ErrorModel : PageModel
 | 
			
		||||
{
 | 
			
		||||
    public string? RequestId { get; set; }
 | 
			
		||||
 | 
			
		||||
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
 | 
			
		||||
 | 
			
		||||
    private readonly ILogger<ErrorModel> _logger;
 | 
			
		||||
 | 
			
		||||
    public ErrorModel(ILogger<ErrorModel> logger)
 | 
			
		||||
    {
 | 
			
		||||
        _logger = logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void OnGet()
 | 
			
		||||
    {
 | 
			
		||||
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								MyWebApp/Pages/Gumby.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,52 @@
 | 
			
		||||
@page
 | 
			
		||||
@model GumbyModel
 | 
			
		||||
@{
 | 
			
		||||
    ViewData["Title"] = "Gumby Page";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<div class="text-center">
 | 
			
		||||
    <h1>Gumby!</h1>
 | 
			
		||||
    <img src="assets/gumby1.webp" width="320px" height="240px" alt="Gumby" id="gumby"/>
 | 
			
		||||
</div>
 | 
			
		||||
<hr/>
 | 
			
		||||
<div class="text-center">
 | 
			
		||||
    <form method="post" class="align-items-center" id="inputForm1">
 | 
			
		||||
        <div class="align-items-center">
 | 
			
		||||
            <table class="align-items-center" style="width: 100%">
 | 
			
		||||
                <tr>
 | 
			
		||||
                    <p>Response from button should be delayed by <span id="delay">a random number of</span> seconds...</p>
 | 
			
		||||
                    <td style="width: 20%; padding-left: 40%"><input type="submit" id="btnPress" value="Press Me!" asp-page-handler="Press"/></td>
 | 
			
		||||
                    <td style="width: 20%; padding-right: 40%"><input type="submit" id="btnClear" value="Clear" asp-page-handler="Clear"/></td>
 | 
			
		||||
                </tr>
 | 
			
		||||
            </table>
 | 
			
		||||
            <hr/>
 | 
			
		||||
            <label id="result"></label>
 | 
			
		||||
        </div>
 | 
			
		||||
    </form>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@if (ViewData["Message"] == null)
 | 
			
		||||
{
 | 
			
		||||
    <script type="text/javascript">
 | 
			
		||||
            window.onload = function () {
 | 
			
		||||
                document.getElementById("result").innerHTML = "";
 | 
			
		||||
            };
 | 
			
		||||
        </script>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<!-- The point of this script is to emulate an indeterminate response from the server -->
 | 
			
		||||
@if (ViewData["Message"] != null)
 | 
			
		||||
{
 | 
			
		||||
    <script type="text/javascript">
 | 
			
		||||
            const viewData = "@ViewData["Message"]"; // imported from controller needs to be wrapped!
 | 
			
		||||
            const delay = ms => new Promise(res => setTimeout(res, ms)); //makeshift delay timer
 | 
			
		||||
            window.onload = async function () {
 | 
			
		||||
                const randTime = Math.random() * 12000; //12 seconds, because playwright is set to 10.
 | 
			
		||||
                const displayTime = Math.round((randTime/1000) *100) / 100;
 | 
			
		||||
                console.log("Delaying " + displayTime + " seconds");
 | 
			
		||||
                document.getElementById("delay").innerHTML = displayTime;
 | 
			
		||||
                await delay(randTime); 
 | 
			
		||||
                document.getElementById("result").innerHTML = viewData;
 | 
			
		||||
            };
 | 
			
		||||
        </script>
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								MyWebApp/Pages/Gumby.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
			
		||||
 | 
			
		||||
namespace MyWebApp.Pages;
 | 
			
		||||
 | 
			
		||||
public class GumbyModel : PageModel
 | 
			
		||||
{
 | 
			
		||||
    public void OnGet()
 | 
			
		||||
    {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public void OnPostPress()
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] = "Yay! You Pressed The Button!";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public void OnPostClear()
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] = null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								MyWebApp/Pages/Index.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,11 @@
 | 
			
		||||
@page
 | 
			
		||||
@model IndexModel
 | 
			
		||||
@{
 | 
			
		||||
    ViewData["Title"] = "Home page";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<div class="text-center">
 | 
			
		||||
    <h1 class="display-4">Welcome</h1>
 | 
			
		||||
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
							
								
								
									
										19
									
								
								MyWebApp/Pages/Index.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,19 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
			
		||||
 | 
			
		||||
namespace MyWebApp.Pages;
 | 
			
		||||
 | 
			
		||||
public class IndexModel : PageModel
 | 
			
		||||
{
 | 
			
		||||
    private readonly ILogger<IndexModel> _logger;
 | 
			
		||||
 | 
			
		||||
    public IndexModel(ILogger<IndexModel> logger)
 | 
			
		||||
    {
 | 
			
		||||
        _logger = logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void OnGet()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								MyWebApp/Pages/Pokey.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,41 @@
 | 
			
		||||
@page
 | 
			
		||||
@model PokeyModel
 | 
			
		||||
@{
 | 
			
		||||
    ViewData["Title"] = "Pokey Page";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<div class="text-center">
 | 
			
		||||
    <h1>Pokey!</h1>
 | 
			
		||||
    <img src=@ViewData["Image"] width="320px" height="240px" alt="Pokey" id="pokey"/>
 | 
			
		||||
</div>
 | 
			
		||||
<hr/>
 | 
			
		||||
<div class="text-center">
 | 
			
		||||
    <!-- Viewdata will disappear when a button is pushed -->
 | 
			
		||||
    <p> @ViewData["Message"]</p>
 | 
			
		||||
    <p>Frontend server time is @DateTime.Now</p>
 | 
			
		||||
</div>
 | 
			
		||||
<hr/>
 | 
			
		||||
 | 
			
		||||
<div class="row" style="width:95%; margin-left: 100px">
 | 
			
		||||
    <div class="col-lg-1" style="width: 25%; padding-left: 15%">
 | 
			
		||||
        <form asp-page-handler="edit" method="post">
 | 
			
		||||
            <button class="btn btn-default">Edit</button>
 | 
			
		||||
            <input type="hidden" name="id" value="1"/>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-lg-1" style="width: 25%; padding-left: 15%">
 | 
			
		||||
        <form asp-page-handler="delete" method="post">
 | 
			
		||||
            <button class="btn btn-default">Delete</button>
 | 
			
		||||
            <input type="hidden" name="id" value="2"/>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-lg-1" style="width: 25%; padding-left: 15%">
 | 
			
		||||
        <form asp-page-handler="view" method="post">
 | 
			
		||||
            <button class="btn btn-default">View</button>
 | 
			
		||||
            <input type="hidden" name="id" value="3"/>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <h4 class="clearfix" style="padding-left: 35%;padding-right: 40%">@Model.Message</h4>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<hr/>
 | 
			
		||||
							
								
								
									
										39
									
								
								MyWebApp/Pages/Pokey.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,39 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
			
		||||
 | 
			
		||||
namespace MyWebApp.Pages;
 | 
			
		||||
 | 
			
		||||
public class PokeyModel : PageModel
 | 
			
		||||
{
 | 
			
		||||
    public string? Message { get; set; }
 | 
			
		||||
    public string? Image { get; set; }
 | 
			
		||||
    
 | 
			
		||||
    public void OnGet()
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] += $" Backend server time is { DateTime.Now }";
 | 
			
		||||
        ViewData["Image"] += "assets/pokey.webp";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public void OnPost()
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] += $" Backend server time is { DateTime.Now }";
 | 
			
		||||
        Message = "Form Posted";
 | 
			
		||||
    }
 | 
			
		||||
    public void OnPostDelete(int id)
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] += $" Backend server time is { DateTime.Now }";
 | 
			
		||||
        Message = $"Delete handler ID: {id}";
 | 
			
		||||
        ViewData["Image"] += "assets/image-missing.jpg";
 | 
			
		||||
    }
 | 
			
		||||
    public void OnPostEdit(int id)
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] += $" Backend server time is { DateTime.Now }";
 | 
			
		||||
        Message = $"Edit handler ID: {id}";
 | 
			
		||||
        ViewData["Image"] += "assets/pokey2.webp";
 | 
			
		||||
    }
 | 
			
		||||
    public void OnPostView(int id)
 | 
			
		||||
    {
 | 
			
		||||
        ViewData["Message"] += $" Backend server time is { DateTime.Now }";
 | 
			
		||||
        Message = $"View handler ID: {id}";
 | 
			
		||||
        ViewData["Image"] += "assets/pokey-where.gif";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								MyWebApp/Pages/Privacy.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,8 @@
 | 
			
		||||
@page
 | 
			
		||||
@model PrivacyModel
 | 
			
		||||
@{
 | 
			
		||||
    ViewData["Title"] = "Privacy Policy";
 | 
			
		||||
}
 | 
			
		||||
<h1>@ViewData["Title"]</h1>
 | 
			
		||||
 | 
			
		||||
<p>Use this page to detail your site's privacy policy.</p>
 | 
			
		||||
							
								
								
									
										19
									
								
								MyWebApp/Pages/Privacy.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,19 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.RazorPages;
 | 
			
		||||
 | 
			
		||||
namespace MyWebApp.Pages;
 | 
			
		||||
 | 
			
		||||
public class PrivacyModel : PageModel
 | 
			
		||||
{
 | 
			
		||||
    private readonly ILogger<PrivacyModel> _logger;
 | 
			
		||||
 | 
			
		||||
    public PrivacyModel(ILogger<PrivacyModel> logger)
 | 
			
		||||
    {
 | 
			
		||||
        _logger = logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void OnGet()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								MyWebApp/Pages/Shared/_Layout.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,57 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
			
		||||
    <title>@ViewData["Title"] - MyWebApp</title>
 | 
			
		||||
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
 | 
			
		||||
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
 | 
			
		||||
    <link rel="stylesheet" href="~/MyWebApp.styles.css" asp-append-version="true" />
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <header>
 | 
			
		||||
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <a class="navbar-brand" asp-area="" asp-page="/Index">MyWebApp</a>
 | 
			
		||||
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
 | 
			
		||||
                        aria-expanded="false" aria-label="Toggle navigation">
 | 
			
		||||
                    <span class="navbar-toggler-icon"></span>
 | 
			
		||||
                </button>
 | 
			
		||||
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
 | 
			
		||||
                    <ul class="navbar-nav flex-grow-1">
 | 
			
		||||
                        <li class="nav-item">
 | 
			
		||||
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li class="nav-item">
 | 
			
		||||
                            <a class="nav-link text-dark" asp-area="" asp-page="/Gumby">Gumby</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li class="nav-item">
 | 
			
		||||
                            <a class="nav-link text-dark" asp-area="" asp-page="/Pokey">Pokey</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li class="nav-item">
 | 
			
		||||
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </nav>
 | 
			
		||||
    </header>
 | 
			
		||||
    <div class="container">
 | 
			
		||||
        <main role="main" class="pb-3">
 | 
			
		||||
            @RenderBody()
 | 
			
		||||
        </main>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <footer class="border-top footer text-muted">
 | 
			
		||||
        <div class="container">
 | 
			
		||||
            © 2023 - MyWebApp - <a asp-area="" asp-page="/Privacy">Privacy</a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </footer>
 | 
			
		||||
 | 
			
		||||
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
 | 
			
		||||
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
 | 
			
		||||
    <script src="~/js/site.js" asp-append-version="true"></script>
 | 
			
		||||
 | 
			
		||||
    @await RenderSectionAsync("Scripts", required: false)
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										48
									
								
								MyWebApp/Pages/Shared/_Layout.cshtml.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,48 @@
 | 
			
		||||
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
 | 
			
		||||
for details on configuring this project to bundle and minify static web assets. */
 | 
			
		||||
 | 
			
		||||
a.navbar-brand {
 | 
			
		||||
  white-space: normal;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
  color: #0077cc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-primary {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  background-color: #1b6ec2;
 | 
			
		||||
  border-color: #1861ac;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  background-color: #1b6ec2;
 | 
			
		||||
  border-color: #1861ac;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-top {
 | 
			
		||||
  border-top: 1px solid #e5e5e5;
 | 
			
		||||
}
 | 
			
		||||
.border-bottom {
 | 
			
		||||
  border-bottom: 1px solid #e5e5e5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.box-shadow {
 | 
			
		||||
  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button.accept-policy {
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.footer {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  line-height: 60px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								MyWebApp/Pages/Shared/_ValidationScriptsPartial.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,2 @@
 | 
			
		||||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
 | 
			
		||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
 | 
			
		||||
							
								
								
									
										3
									
								
								MyWebApp/Pages/_ViewImports.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,3 @@
 | 
			
		||||
@using MyWebApp
 | 
			
		||||
@namespace MyWebApp.Pages
 | 
			
		||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
 | 
			
		||||
							
								
								
									
										3
									
								
								MyWebApp/Pages/_ViewStart.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,3 @@
 | 
			
		||||
@{
 | 
			
		||||
    Layout = "_Layout";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								MyWebApp/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
var builder = WebApplication.CreateBuilder(args);
 | 
			
		||||
 | 
			
		||||
// Add services to the container.
 | 
			
		||||
builder.Services.AddRazorPages();
 | 
			
		||||
 | 
			
		||||
var app = builder.Build();
 | 
			
		||||
 | 
			
		||||
// Configure the HTTP request pipeline.
 | 
			
		||||
if (!app.Environment.IsDevelopment())
 | 
			
		||||
{
 | 
			
		||||
    app.UseExceptionHandler("/Error");
 | 
			
		||||
}
 | 
			
		||||
app.UseStaticFiles();
 | 
			
		||||
 | 
			
		||||
app.UseRouting();
 | 
			
		||||
 | 
			
		||||
app.UseAuthorization();
 | 
			
		||||
 | 
			
		||||
app.MapRazorPages();
 | 
			
		||||
 | 
			
		||||
app.Run();
 | 
			
		||||
							
								
								
									
										28
									
								
								MyWebApp/Properties/launchSettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
  "iisSettings": {
 | 
			
		||||
    "windowsAuthentication": false,
 | 
			
		||||
    "anonymousAuthentication": true,
 | 
			
		||||
    "iisExpress": {
 | 
			
		||||
      "applicationUrl": "http://localhost:5847",
 | 
			
		||||
      "sslPort": 0
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "profiles": {
 | 
			
		||||
    "http": {
 | 
			
		||||
      "commandName": "Project",
 | 
			
		||||
      "dotnetRunMessages": true,
 | 
			
		||||
      "launchBrowser": true,
 | 
			
		||||
      "applicationUrl": "http://localhost:5296",
 | 
			
		||||
      "environmentVariables": {
 | 
			
		||||
        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "IIS Express": {
 | 
			
		||||
      "commandName": "IISExpress",
 | 
			
		||||
      "launchBrowser": true,
 | 
			
		||||
      "environmentVariables": {
 | 
			
		||||
        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								MyWebApp/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,29 @@
 | 
			
		||||
# MyWebApp
 | 
			
		||||
 | 
			
		||||
A generic default ASP.NET web app, for use as a punch-dummy for testing tools like PlayWright and Cypress.
 | 
			
		||||
 | 
			
		||||
Feel free to fork this, and modify it as needed. 
 | 
			
		||||
 | 
			
		||||
### Run
 | 
			
		||||
```bash
 | 
			
		||||
$ dotnet watch                                                                                                           (15m)|*[main]  
 | 
			
		||||
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
 | 
			
		||||
  💡 Press "Ctrl + R" to restart.
 | 
			
		||||
dotnet watch 🔧 Building...
 | 
			
		||||
  Determining projects to restore...
 | 
			
		||||
  All projects are up-to-date for restore.
 | 
			
		||||
  MyWebApp -> /Users/YOU/Projects/YOUR_PROJECTS/MyWebApp/bin/Debug/net7.0/MyWebApp.dll
 | 
			
		||||
dotnet watch 🚀 Started
 | 
			
		||||
info: Microsoft.Hosting.Lifetime[14]
 | 
			
		||||
      Now listening on: http://localhost:5296
 | 
			
		||||
info: Microsoft.Hosting.Lifetime[0]
 | 
			
		||||
      Application started. Press Ctrl+C to shut down.
 | 
			
		||||
info: Microsoft.Hosting.Lifetime[0]
 | 
			
		||||
      Hosting environment: Development
 | 
			
		||||
info: Microsoft.Hosting.Lifetime[0]
 | 
			
		||||
      Content root path: /Users/YOU/Projects/YOUR_PROJECTS/MyWebApp
 | 
			
		||||
```
 | 
			
		||||
Your default browser will fire up once the app is loaded, and will navigate to the localhost port where the app is hosted. You should see a "Gumby" page in the header links.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								MyWebApp/appsettings.Development.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "DetailedErrors": true,
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Information",
 | 
			
		||||
      "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								MyWebApp/appsettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Information",
 | 
			
		||||
      "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "AllowedHosts": "*"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/MyWebApp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 115 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/gumby.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 68 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/gumby1.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 7.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/image-missing.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 17 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/pokey-where.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.3 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/pokey.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/assets/pokey2.webp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 131 KiB  | 
							
								
								
									
										23
									
								
								MyWebApp/wwwroot/css/site.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,23 @@
 | 
			
		||||
html {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-width: 768px) {
 | 
			
		||||
  html {
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
 | 
			
		||||
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  min-height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  margin-bottom: 60px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								MyWebApp/wwwroot/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.3 KiB  | 
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/js/site.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								MyWebApp/wwwroot/lib/bootstrap/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,22 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2011-2021 Twitter, Inc.
 | 
			
		||||
Copyright (c) 2011-2021 The Bootstrap Authors
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										4997
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4996
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										427
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,427 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
 | 
			
		||||
 * Copyright 2011-2021 The Bootstrap Authors
 | 
			
		||||
 * Copyright 2011-2021 Twitter, Inc.
 | 
			
		||||
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
			
		||||
 * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
 | 
			
		||||
 */
 | 
			
		||||
*,
 | 
			
		||||
*::before,
 | 
			
		||||
*::after {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (prefers-reduced-motion: no-preference) {
 | 
			
		||||
  :root {
 | 
			
		||||
    scroll-behavior: smooth;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: var(--bs-body-font-family);
 | 
			
		||||
  font-size: var(--bs-body-font-size);
 | 
			
		||||
  font-weight: var(--bs-body-font-weight);
 | 
			
		||||
  line-height: var(--bs-body-line-height);
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  text-align: var(--bs-body-text-align);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  -webkit-text-size-adjust: 100%;
 | 
			
		||||
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hr {
 | 
			
		||||
  margin: 1rem 0;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  background-color: currentColor;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  opacity: 0.25;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hr:not([size]) {
 | 
			
		||||
  height: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h6, h5, h4, h3, h2, h1 {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  line-height: 1.2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
  font-size: calc(1.375rem + 1.5vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h1 {
 | 
			
		||||
    font-size: 2.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
  font-size: calc(1.325rem + 0.9vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h2 {
 | 
			
		||||
    font-size: 2rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h3 {
 | 
			
		||||
  font-size: calc(1.3rem + 0.6vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h3 {
 | 
			
		||||
    font-size: 1.75rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 {
 | 
			
		||||
  font-size: calc(1.275rem + 0.3vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h4 {
 | 
			
		||||
    font-size: 1.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h5 {
 | 
			
		||||
  font-size: 1.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h6 {
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abbr[title],
 | 
			
		||||
abbr[data-bs-original-title] {
 | 
			
		||||
  -webkit-text-decoration: underline dotted;
 | 
			
		||||
  text-decoration: underline dotted;
 | 
			
		||||
  cursor: help;
 | 
			
		||||
  -webkit-text-decoration-skip-ink: none;
 | 
			
		||||
  text-decoration-skip-ink: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
address {
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol,
 | 
			
		||||
ul {
 | 
			
		||||
  padding-left: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol,
 | 
			
		||||
ul,
 | 
			
		||||
dl {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol ol,
 | 
			
		||||
ul ul,
 | 
			
		||||
ol ul,
 | 
			
		||||
ul ol {
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dt {
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dd {
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  margin-left: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
blockquote {
 | 
			
		||||
  margin: 0 0 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b,
 | 
			
		||||
strong {
 | 
			
		||||
  font-weight: bolder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
small {
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mark {
 | 
			
		||||
  padding: 0.2em;
 | 
			
		||||
  background-color: #fcf8e3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub,
 | 
			
		||||
sup {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  font-size: 0.75em;
 | 
			
		||||
  line-height: 0;
 | 
			
		||||
  vertical-align: baseline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub {
 | 
			
		||||
  bottom: -0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sup {
 | 
			
		||||
  top: -0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
  color: #0d6efd;
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
a:hover {
 | 
			
		||||
  color: #0a58ca;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pre,
 | 
			
		||||
code,
 | 
			
		||||
kbd,
 | 
			
		||||
samp {
 | 
			
		||||
  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
 | 
			
		||||
  font-size: 1em;
 | 
			
		||||
  direction: ltr /* rtl:ignore */;
 | 
			
		||||
  unicode-bidi: bidi-override;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
  display: block;
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
}
 | 
			
		||||
pre code {
 | 
			
		||||
  font-size: inherit;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  word-break: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
  color: #d63384;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
}
 | 
			
		||||
a > code {
 | 
			
		||||
  color: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
kbd {
 | 
			
		||||
  padding: 0.2rem 0.4rem;
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  background-color: #212529;
 | 
			
		||||
  border-radius: 0.2rem;
 | 
			
		||||
}
 | 
			
		||||
kbd kbd {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  font-size: 1em;
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
figure {
 | 
			
		||||
  margin: 0 0 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img,
 | 
			
		||||
svg {
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table {
 | 
			
		||||
  caption-side: bottom;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
caption {
 | 
			
		||||
  padding-top: 0.5rem;
 | 
			
		||||
  padding-bottom: 0.5rem;
 | 
			
		||||
  color: #6c757d;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th {
 | 
			
		||||
  text-align: inherit;
 | 
			
		||||
  text-align: -webkit-match-parent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
thead,
 | 
			
		||||
tbody,
 | 
			
		||||
tfoot,
 | 
			
		||||
tr,
 | 
			
		||||
td,
 | 
			
		||||
th {
 | 
			
		||||
  border-color: inherit;
 | 
			
		||||
  border-style: solid;
 | 
			
		||||
  border-width: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
label {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
  border-radius: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:focus:not(:focus-visible) {
 | 
			
		||||
  outline: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input,
 | 
			
		||||
button,
 | 
			
		||||
select,
 | 
			
		||||
optgroup,
 | 
			
		||||
textarea {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: inherit;
 | 
			
		||||
  font-size: inherit;
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
select {
 | 
			
		||||
  text-transform: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[role=button] {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select {
 | 
			
		||||
  word-wrap: normal;
 | 
			
		||||
}
 | 
			
		||||
select:disabled {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[list]::-webkit-calendar-picker-indicator {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
[type=button],
 | 
			
		||||
[type=reset],
 | 
			
		||||
[type=submit] {
 | 
			
		||||
  -webkit-appearance: button;
 | 
			
		||||
}
 | 
			
		||||
button:not(:disabled),
 | 
			
		||||
[type=button]:not(:disabled),
 | 
			
		||||
[type=reset]:not(:disabled),
 | 
			
		||||
[type=submit]:not(:disabled) {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-moz-focus-inner {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  border-style: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
  resize: vertical;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fieldset {
 | 
			
		||||
  min-width: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
legend {
 | 
			
		||||
  float: left;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  font-size: calc(1.275rem + 0.3vw);
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  legend {
 | 
			
		||||
    font-size: 1.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
legend + * {
 | 
			
		||||
  clear: left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-datetime-edit-fields-wrapper,
 | 
			
		||||
::-webkit-datetime-edit-text,
 | 
			
		||||
::-webkit-datetime-edit-minute,
 | 
			
		||||
::-webkit-datetime-edit-hour-field,
 | 
			
		||||
::-webkit-datetime-edit-day-field,
 | 
			
		||||
::-webkit-datetime-edit-month-field,
 | 
			
		||||
::-webkit-datetime-edit-year-field {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-inner-spin-button {
 | 
			
		||||
  height: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[type=search] {
 | 
			
		||||
  outline-offset: -2px;
 | 
			
		||||
  -webkit-appearance: textfield;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* rtl:raw:
 | 
			
		||||
[type="tel"],
 | 
			
		||||
[type="url"],
 | 
			
		||||
[type="email"],
 | 
			
		||||
[type="number"] {
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
::-webkit-search-decoration {
 | 
			
		||||
  -webkit-appearance: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-color-swatch-wrapper {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::file-selector-button {
 | 
			
		||||
  font: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-file-upload-button {
 | 
			
		||||
  font: inherit;
 | 
			
		||||
  -webkit-appearance: button;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
output {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
iframe {
 | 
			
		||||
  border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
summary {
 | 
			
		||||
  display: list-item;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
progress {
 | 
			
		||||
  vertical-align: baseline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[hidden] {
 | 
			
		||||
  display: none !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										8
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,8 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
 | 
			
		||||
 * Copyright 2011-2021 The Bootstrap Authors
 | 
			
		||||
 * Copyright 2011-2021 Twitter, Inc.
 | 
			
		||||
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
			
		||||
 * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
 | 
			
		||||
 */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
 | 
			
		||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										424
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,424 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
 | 
			
		||||
 * Copyright 2011-2021 The Bootstrap Authors
 | 
			
		||||
 * Copyright 2011-2021 Twitter, Inc.
 | 
			
		||||
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
			
		||||
 * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
 | 
			
		||||
 */
 | 
			
		||||
*,
 | 
			
		||||
*::before,
 | 
			
		||||
*::after {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (prefers-reduced-motion: no-preference) {
 | 
			
		||||
  :root {
 | 
			
		||||
    scroll-behavior: smooth;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: var(--bs-body-font-family);
 | 
			
		||||
  font-size: var(--bs-body-font-size);
 | 
			
		||||
  font-weight: var(--bs-body-font-weight);
 | 
			
		||||
  line-height: var(--bs-body-line-height);
 | 
			
		||||
  color: var(--bs-body-color);
 | 
			
		||||
  text-align: var(--bs-body-text-align);
 | 
			
		||||
  background-color: var(--bs-body-bg);
 | 
			
		||||
  -webkit-text-size-adjust: 100%;
 | 
			
		||||
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hr {
 | 
			
		||||
  margin: 1rem 0;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  background-color: currentColor;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  opacity: 0.25;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
hr:not([size]) {
 | 
			
		||||
  height: 1px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h6, h5, h4, h3, h2, h1 {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  line-height: 1.2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
  font-size: calc(1.375rem + 1.5vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h1 {
 | 
			
		||||
    font-size: 2.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
  font-size: calc(1.325rem + 0.9vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h2 {
 | 
			
		||||
    font-size: 2rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h3 {
 | 
			
		||||
  font-size: calc(1.3rem + 0.6vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h3 {
 | 
			
		||||
    font-size: 1.75rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h4 {
 | 
			
		||||
  font-size: calc(1.275rem + 0.3vw);
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  h4 {
 | 
			
		||||
    font-size: 1.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h5 {
 | 
			
		||||
  font-size: 1.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h6 {
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abbr[title],
 | 
			
		||||
abbr[data-bs-original-title] {
 | 
			
		||||
  -webkit-text-decoration: underline dotted;
 | 
			
		||||
  text-decoration: underline dotted;
 | 
			
		||||
  cursor: help;
 | 
			
		||||
  -webkit-text-decoration-skip-ink: none;
 | 
			
		||||
  text-decoration-skip-ink: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
address {
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol,
 | 
			
		||||
ul {
 | 
			
		||||
  padding-right: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol,
 | 
			
		||||
ul,
 | 
			
		||||
dl {
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ol ol,
 | 
			
		||||
ul ul,
 | 
			
		||||
ol ul,
 | 
			
		||||
ul ol {
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dt {
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dd {
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
blockquote {
 | 
			
		||||
  margin: 0 0 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b,
 | 
			
		||||
strong {
 | 
			
		||||
  font-weight: bolder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
small {
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mark {
 | 
			
		||||
  padding: 0.2em;
 | 
			
		||||
  background-color: #fcf8e3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub,
 | 
			
		||||
sup {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  font-size: 0.75em;
 | 
			
		||||
  line-height: 0;
 | 
			
		||||
  vertical-align: baseline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub {
 | 
			
		||||
  bottom: -0.25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sup {
 | 
			
		||||
  top: -0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
  color: #0d6efd;
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
a:hover {
 | 
			
		||||
  color: #0a58ca;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pre,
 | 
			
		||||
code,
 | 
			
		||||
kbd,
 | 
			
		||||
samp {
 | 
			
		||||
  font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
 | 
			
		||||
  font-size: 1em;
 | 
			
		||||
  direction: ltr ;
 | 
			
		||||
  unicode-bidi: bidi-override;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
  display: block;
 | 
			
		||||
  margin-top: 0;
 | 
			
		||||
  margin-bottom: 1rem;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
}
 | 
			
		||||
pre code {
 | 
			
		||||
  font-size: inherit;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  word-break: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
  color: #d63384;
 | 
			
		||||
  word-wrap: break-word;
 | 
			
		||||
}
 | 
			
		||||
a > code {
 | 
			
		||||
  color: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
kbd {
 | 
			
		||||
  padding: 0.2rem 0.4rem;
 | 
			
		||||
  font-size: 0.875em;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  background-color: #212529;
 | 
			
		||||
  border-radius: 0.2rem;
 | 
			
		||||
}
 | 
			
		||||
kbd kbd {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  font-size: 1em;
 | 
			
		||||
  font-weight: 700;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
figure {
 | 
			
		||||
  margin: 0 0 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img,
 | 
			
		||||
svg {
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table {
 | 
			
		||||
  caption-side: bottom;
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
caption {
 | 
			
		||||
  padding-top: 0.5rem;
 | 
			
		||||
  padding-bottom: 0.5rem;
 | 
			
		||||
  color: #6c757d;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
th {
 | 
			
		||||
  text-align: inherit;
 | 
			
		||||
  text-align: -webkit-match-parent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
thead,
 | 
			
		||||
tbody,
 | 
			
		||||
tfoot,
 | 
			
		||||
tr,
 | 
			
		||||
td,
 | 
			
		||||
th {
 | 
			
		||||
  border-color: inherit;
 | 
			
		||||
  border-style: solid;
 | 
			
		||||
  border-width: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
label {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button {
 | 
			
		||||
  border-radius: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button:focus:not(:focus-visible) {
 | 
			
		||||
  outline: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input,
 | 
			
		||||
button,
 | 
			
		||||
select,
 | 
			
		||||
optgroup,
 | 
			
		||||
textarea {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: inherit;
 | 
			
		||||
  font-size: inherit;
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
select {
 | 
			
		||||
  text-transform: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[role=button] {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select {
 | 
			
		||||
  word-wrap: normal;
 | 
			
		||||
}
 | 
			
		||||
select:disabled {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[list]::-webkit-calendar-picker-indicator {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
button,
 | 
			
		||||
[type=button],
 | 
			
		||||
[type=reset],
 | 
			
		||||
[type=submit] {
 | 
			
		||||
  -webkit-appearance: button;
 | 
			
		||||
}
 | 
			
		||||
button:not(:disabled),
 | 
			
		||||
[type=button]:not(:disabled),
 | 
			
		||||
[type=reset]:not(:disabled),
 | 
			
		||||
[type=submit]:not(:disabled) {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-moz-focus-inner {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  border-style: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
  resize: vertical;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fieldset {
 | 
			
		||||
  min-width: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
legend {
 | 
			
		||||
  float: right;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  margin-bottom: 0.5rem;
 | 
			
		||||
  font-size: calc(1.275rem + 0.3vw);
 | 
			
		||||
  line-height: inherit;
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 1200px) {
 | 
			
		||||
  legend {
 | 
			
		||||
    font-size: 1.5rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
legend + * {
 | 
			
		||||
  clear: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-datetime-edit-fields-wrapper,
 | 
			
		||||
::-webkit-datetime-edit-text,
 | 
			
		||||
::-webkit-datetime-edit-minute,
 | 
			
		||||
::-webkit-datetime-edit-hour-field,
 | 
			
		||||
::-webkit-datetime-edit-day-field,
 | 
			
		||||
::-webkit-datetime-edit-month-field,
 | 
			
		||||
::-webkit-datetime-edit-year-field {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-inner-spin-button {
 | 
			
		||||
  height: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[type=search] {
 | 
			
		||||
  outline-offset: -2px;
 | 
			
		||||
  -webkit-appearance: textfield;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[type="tel"],
 | 
			
		||||
[type="url"],
 | 
			
		||||
[type="email"],
 | 
			
		||||
[type="number"] {
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
}
 | 
			
		||||
::-webkit-search-decoration {
 | 
			
		||||
  -webkit-appearance: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-color-swatch-wrapper {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::file-selector-button {
 | 
			
		||||
  font: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
::-webkit-file-upload-button {
 | 
			
		||||
  font: inherit;
 | 
			
		||||
  -webkit-appearance: button;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
output {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
iframe {
 | 
			
		||||
  border: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
summary {
 | 
			
		||||
  display: list-item;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
progress {
 | 
			
		||||
  vertical-align: baseline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[hidden] {
 | 
			
		||||
  display: none !important;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										8
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,8 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/)
 | 
			
		||||
 * Copyright 2011-2021 The Bootstrap Authors
 | 
			
		||||
 * Copyright 2011-2021 Twitter, Inc.
 | 
			
		||||
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 | 
			
		||||
 * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
 | 
			
		||||
 */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
 | 
			
		||||
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4866
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4857
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										11221
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										11197
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										6780
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4977
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5026
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,23 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) .NET Foundation and Contributors
 | 
			
		||||
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
							
								
								
									
										435
									
								
								MyWebApp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,435 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @license
 | 
			
		||||
 * Unobtrusive validation support library for jQuery and jQuery Validate
 | 
			
		||||
 * Copyright (c) .NET Foundation. All rights reserved.
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 | 
			
		||||
 * @version v4.0.0
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
 | 
			
		||||
/*global document: false, jQuery: false */
 | 
			
		||||
 | 
			
		||||
(function (factory) {
 | 
			
		||||
    if (typeof define === 'function' && define.amd) {
 | 
			
		||||
        // AMD. Register as an anonymous module.
 | 
			
		||||
        define("jquery.validate.unobtrusive", ['jquery-validation'], factory);
 | 
			
		||||
    } else if (typeof module === 'object' && module.exports) {
 | 
			
		||||
        // CommonJS-like environments that support module.exports     
 | 
			
		||||
        module.exports = factory(require('jquery-validation'));
 | 
			
		||||
    } else {
 | 
			
		||||
        // Browser global
 | 
			
		||||
        jQuery.validator.unobtrusive = factory(jQuery);
 | 
			
		||||
    }
 | 
			
		||||
}(function ($) {
 | 
			
		||||
    var $jQval = $.validator,
 | 
			
		||||
        adapters,
 | 
			
		||||
        data_validation = "unobtrusiveValidation";
 | 
			
		||||
 | 
			
		||||
    function setValidationValues(options, ruleName, value) {
 | 
			
		||||
        options.rules[ruleName] = value;
 | 
			
		||||
        if (options.message) {
 | 
			
		||||
            options.messages[ruleName] = options.message;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function splitAndTrim(value) {
 | 
			
		||||
        return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function escapeAttributeValue(value) {
 | 
			
		||||
        // As mentioned on http://api.jquery.com/category/selectors/
 | 
			
		||||
        return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getModelPrefix(fieldName) {
 | 
			
		||||
        return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function appendModelPrefix(value, prefix) {
 | 
			
		||||
        if (value.indexOf("*.") === 0) {
 | 
			
		||||
            value = value.replace("*.", prefix);
 | 
			
		||||
        }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onError(error, inputElement) {  // 'this' is the form element
 | 
			
		||||
        var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
 | 
			
		||||
            replaceAttrValue = container.attr("data-valmsg-replace"),
 | 
			
		||||
            replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
 | 
			
		||||
 | 
			
		||||
        container.removeClass("field-validation-valid").addClass("field-validation-error");
 | 
			
		||||
        error.data("unobtrusiveContainer", container);
 | 
			
		||||
 | 
			
		||||
        if (replace) {
 | 
			
		||||
            container.empty();
 | 
			
		||||
            error.removeClass("input-validation-error").appendTo(container);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            error.hide();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onErrors(event, validator) {  // 'this' is the form element
 | 
			
		||||
        var container = $(this).find("[data-valmsg-summary=true]"),
 | 
			
		||||
            list = container.find("ul");
 | 
			
		||||
 | 
			
		||||
        if (list && list.length && validator.errorList.length) {
 | 
			
		||||
            list.empty();
 | 
			
		||||
            container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
 | 
			
		||||
 | 
			
		||||
            $.each(validator.errorList, function () {
 | 
			
		||||
                $("<li />").html(this.message).appendTo(list);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onSuccess(error) {  // 'this' is the form element
 | 
			
		||||
        var container = error.data("unobtrusiveContainer");
 | 
			
		||||
 | 
			
		||||
        if (container) {
 | 
			
		||||
            var replaceAttrValue = container.attr("data-valmsg-replace"),
 | 
			
		||||
                replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
 | 
			
		||||
 | 
			
		||||
            container.addClass("field-validation-valid").removeClass("field-validation-error");
 | 
			
		||||
            error.removeData("unobtrusiveContainer");
 | 
			
		||||
 | 
			
		||||
            if (replace) {
 | 
			
		||||
                container.empty();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onReset(event) {  // 'this' is the form element
 | 
			
		||||
        var $form = $(this),
 | 
			
		||||
            key = '__jquery_unobtrusive_validation_form_reset';
 | 
			
		||||
        if ($form.data(key)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Set a flag that indicates we're currently resetting the form.
 | 
			
		||||
        $form.data(key, true);
 | 
			
		||||
        try {
 | 
			
		||||
            $form.data("validator").resetForm();
 | 
			
		||||
        } finally {
 | 
			
		||||
            $form.removeData(key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $form.find(".validation-summary-errors")
 | 
			
		||||
            .addClass("validation-summary-valid")
 | 
			
		||||
            .removeClass("validation-summary-errors");
 | 
			
		||||
        $form.find(".field-validation-error")
 | 
			
		||||
            .addClass("field-validation-valid")
 | 
			
		||||
            .removeClass("field-validation-error")
 | 
			
		||||
            .removeData("unobtrusiveContainer")
 | 
			
		||||
            .find(">*")  // If we were using valmsg-replace, get the underlying error
 | 
			
		||||
            .removeData("unobtrusiveContainer");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function validationInfo(form) {
 | 
			
		||||
        var $form = $(form),
 | 
			
		||||
            result = $form.data(data_validation),
 | 
			
		||||
            onResetProxy = $.proxy(onReset, form),
 | 
			
		||||
            defaultOptions = $jQval.unobtrusive.options || {},
 | 
			
		||||
            execInContext = function (name, args) {
 | 
			
		||||
                var func = defaultOptions[name];
 | 
			
		||||
                func && $.isFunction(func) && func.apply(form, args);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        if (!result) {
 | 
			
		||||
            result = {
 | 
			
		||||
                options: {  // options structure passed to jQuery Validate's validate() method
 | 
			
		||||
                    errorClass: defaultOptions.errorClass || "input-validation-error",
 | 
			
		||||
                    errorElement: defaultOptions.errorElement || "span",
 | 
			
		||||
                    errorPlacement: function () {
 | 
			
		||||
                        onError.apply(form, arguments);
 | 
			
		||||
                        execInContext("errorPlacement", arguments);
 | 
			
		||||
                    },
 | 
			
		||||
                    invalidHandler: function () {
 | 
			
		||||
                        onErrors.apply(form, arguments);
 | 
			
		||||
                        execInContext("invalidHandler", arguments);
 | 
			
		||||
                    },
 | 
			
		||||
                    messages: {},
 | 
			
		||||
                    rules: {},
 | 
			
		||||
                    success: function () {
 | 
			
		||||
                        onSuccess.apply(form, arguments);
 | 
			
		||||
                        execInContext("success", arguments);
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                attachValidation: function () {
 | 
			
		||||
                    $form
 | 
			
		||||
                        .off("reset." + data_validation, onResetProxy)
 | 
			
		||||
                        .on("reset." + data_validation, onResetProxy)
 | 
			
		||||
                        .validate(this.options);
 | 
			
		||||
                },
 | 
			
		||||
                validate: function () {  // a validation function that is called by unobtrusive Ajax
 | 
			
		||||
                    $form.validate();
 | 
			
		||||
                    return $form.valid();
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            $form.data(data_validation, result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $jQval.unobtrusive = {
 | 
			
		||||
        adapters: [],
 | 
			
		||||
 | 
			
		||||
        parseElement: function (element, skipAttach) {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Parses a single HTML element for unobtrusive validation attributes.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            /// <param name="element" domElement="true">The HTML element to be parsed.</param>
 | 
			
		||||
            /// <param name="skipAttach" type="Boolean">[Optional] true to skip attaching the
 | 
			
		||||
            /// validation to the form. If parsing just this single element, you should specify true.
 | 
			
		||||
            /// If parsing several elements, you should specify false, and manually attach the validation
 | 
			
		||||
            /// to the form when you are finished. The default is false.</param>
 | 
			
		||||
            var $element = $(element),
 | 
			
		||||
                form = $element.parents("form")[0],
 | 
			
		||||
                valInfo, rules, messages;
 | 
			
		||||
 | 
			
		||||
            if (!form) {  // Cannot do client-side validation without a form
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            valInfo = validationInfo(form);
 | 
			
		||||
            valInfo.options.rules[element.name] = rules = {};
 | 
			
		||||
            valInfo.options.messages[element.name] = messages = {};
 | 
			
		||||
 | 
			
		||||
            $.each(this.adapters, function () {
 | 
			
		||||
                var prefix = "data-val-" + this.name,
 | 
			
		||||
                    message = $element.attr(prefix),
 | 
			
		||||
                    paramValues = {};
 | 
			
		||||
 | 
			
		||||
                if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)
 | 
			
		||||
                    prefix += "-";
 | 
			
		||||
 | 
			
		||||
                    $.each(this.params, function () {
 | 
			
		||||
                        paramValues[this] = $element.attr(prefix + this);
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    this.adapt({
 | 
			
		||||
                        element: element,
 | 
			
		||||
                        form: form,
 | 
			
		||||
                        message: message,
 | 
			
		||||
                        params: paramValues,
 | 
			
		||||
                        rules: rules,
 | 
			
		||||
                        messages: messages
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            $.extend(rules, { "__dummy__": true });
 | 
			
		||||
 | 
			
		||||
            if (!skipAttach) {
 | 
			
		||||
                valInfo.attachValidation();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        parse: function (selector) {
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
 | 
			
		||||
            /// with the [data-val=true] attribute value and enables validation according to the data-val-*
 | 
			
		||||
            /// attribute values.
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            /// <param name="selector" type="String">Any valid jQuery selector.</param>
 | 
			
		||||
 | 
			
		||||
            // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one
 | 
			
		||||
            // element with data-val=true
 | 
			
		||||
            var $selector = $(selector),
 | 
			
		||||
                $forms = $selector.parents()
 | 
			
		||||
                    .addBack()
 | 
			
		||||
                    .filter("form")
 | 
			
		||||
                    .add($selector.find("form"))
 | 
			
		||||
                    .has("[data-val=true]");
 | 
			
		||||
 | 
			
		||||
            $selector.find("[data-val=true]").each(function () {
 | 
			
		||||
                $jQval.unobtrusive.parseElement(this, true);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            $forms.each(function () {
 | 
			
		||||
                var info = validationInfo(this);
 | 
			
		||||
                if (info) {
 | 
			
		||||
                    info.attachValidation();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    adapters = $jQval.unobtrusive.adapters;
 | 
			
		||||
 | 
			
		||||
    adapters.add = function (adapterName, params, fn) {
 | 
			
		||||
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>
 | 
			
		||||
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
 | 
			
		||||
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
 | 
			
		||||
        /// <param name="params" type="Array" optional="true">[Optional] An array of parameter names (strings) that will
 | 
			
		||||
        /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
 | 
			
		||||
        /// mmmm is the parameter name).</param>
 | 
			
		||||
        /// <param name="fn" type="Function">The function to call, which adapts the values from the HTML
 | 
			
		||||
        /// attributes into jQuery Validate rules and/or messages.</param>
 | 
			
		||||
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
 | 
			
		||||
        if (!fn) {  // Called with no params, just a function
 | 
			
		||||
            fn = params;
 | 
			
		||||
            params = [];
 | 
			
		||||
        }
 | 
			
		||||
        this.push({ name: adapterName, params: params, adapt: fn });
 | 
			
		||||
        return this;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    adapters.addBool = function (adapterName, ruleName) {
 | 
			
		||||
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
 | 
			
		||||
        /// the jQuery Validate validation rule has no parameter values.</summary>
 | 
			
		||||
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
 | 
			
		||||
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
 | 
			
		||||
        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
 | 
			
		||||
        /// of adapterName will be used instead.</param>
 | 
			
		||||
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
 | 
			
		||||
        return this.add(adapterName, function (options) {
 | 
			
		||||
            setValidationValues(options, ruleName || adapterName, true);
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
 | 
			
		||||
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
 | 
			
		||||
        /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
 | 
			
		||||
        /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>
 | 
			
		||||
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
 | 
			
		||||
        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>
 | 
			
		||||
        /// <param name="minRuleName" type="String">The name of the jQuery Validate rule to be used when you only
 | 
			
		||||
        /// have a minimum value.</param>
 | 
			
		||||
        /// <param name="maxRuleName" type="String">The name of the jQuery Validate rule to be used when you only
 | 
			
		||||
        /// have a maximum value.</param>
 | 
			
		||||
        /// <param name="minMaxRuleName" type="String">The name of the jQuery Validate rule to be used when you
 | 
			
		||||
        /// have both a minimum and maximum value.</param>
 | 
			
		||||
        /// <param name="minAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
 | 
			
		||||
        /// contains the minimum value. The default is "min".</param>
 | 
			
		||||
        /// <param name="maxAttribute" type="String" optional="true">[Optional] The name of the HTML attribute that
 | 
			
		||||
        /// contains the maximum value. The default is "max".</param>
 | 
			
		||||
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
 | 
			
		||||
        return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
 | 
			
		||||
            var min = options.params.min,
 | 
			
		||||
                max = options.params.max;
 | 
			
		||||
 | 
			
		||||
            if (min && max) {
 | 
			
		||||
                setValidationValues(options, minMaxRuleName, [min, max]);
 | 
			
		||||
            }
 | 
			
		||||
            else if (min) {
 | 
			
		||||
                setValidationValues(options, minRuleName, min);
 | 
			
		||||
            }
 | 
			
		||||
            else if (max) {
 | 
			
		||||
                setValidationValues(options, maxRuleName, max);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    adapters.addSingleVal = function (adapterName, attribute, ruleName) {
 | 
			
		||||
        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
 | 
			
		||||
        /// the jQuery Validate validation rule has a single value.</summary>
 | 
			
		||||
        /// <param name="adapterName" type="String">The name of the adapter to be added. This matches the name used
 | 
			
		||||
        /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>
 | 
			
		||||
        /// <param name="attribute" type="String">[Optional] The name of the HTML attribute that contains the value.
 | 
			
		||||
        /// The default is "val".</param>
 | 
			
		||||
        /// <param name="ruleName" type="String" optional="true">[Optional] The name of the jQuery Validate rule. If not provided, the value
 | 
			
		||||
        /// of adapterName will be used instead.</param>
 | 
			
		||||
        /// <returns type="jQuery.validator.unobtrusive.adapters" />
 | 
			
		||||
        return this.add(adapterName, [attribute || "val"], function (options) {
 | 
			
		||||
            setValidationValues(options, ruleName || adapterName, options.params[attribute]);
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $jQval.addMethod("__dummy__", function (value, element, params) {
 | 
			
		||||
        return true;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $jQval.addMethod("regex", function (value, element, params) {
 | 
			
		||||
        var match;
 | 
			
		||||
        if (this.optional(element)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        match = new RegExp(params).exec(value);
 | 
			
		||||
        return (match && (match.index === 0) && (match[0].length === value.length));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
 | 
			
		||||
        var match;
 | 
			
		||||
        if (nonalphamin) {
 | 
			
		||||
            match = value.match(/\W/g);
 | 
			
		||||
            match = match && match.length >= nonalphamin;
 | 
			
		||||
        }
 | 
			
		||||
        return match;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if ($jQval.methods.extension) {
 | 
			
		||||
        adapters.addSingleVal("accept", "mimtype");
 | 
			
		||||
        adapters.addSingleVal("extension", "extension");
 | 
			
		||||
    } else {
 | 
			
		||||
        // for backward compatibility, when the 'extension' validation method does not exist, such as with versions
 | 
			
		||||
        // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
 | 
			
		||||
        // validating the extension, and ignore mime-type validations as they are not supported.
 | 
			
		||||
        adapters.addSingleVal("extension", "extension", "accept");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    adapters.addSingleVal("regex", "pattern");
 | 
			
		||||
    adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
 | 
			
		||||
    adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
 | 
			
		||||
    adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength");
 | 
			
		||||
    adapters.add("equalto", ["other"], function (options) {
 | 
			
		||||
        var prefix = getModelPrefix(options.element.name),
 | 
			
		||||
            other = options.params.other,
 | 
			
		||||
            fullOtherName = appendModelPrefix(other, prefix),
 | 
			
		||||
            element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
 | 
			
		||||
 | 
			
		||||
        setValidationValues(options, "equalTo", element);
 | 
			
		||||
    });
 | 
			
		||||
    adapters.add("required", function (options) {
 | 
			
		||||
        // jQuery Validate equates "required" with "mandatory" for checkbox elements
 | 
			
		||||
        if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
 | 
			
		||||
            setValidationValues(options, "required", true);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
 | 
			
		||||
        var value = {
 | 
			
		||||
            url: options.params.url,
 | 
			
		||||
            type: options.params.type || "GET",
 | 
			
		||||
            data: {}
 | 
			
		||||
        },
 | 
			
		||||
            prefix = getModelPrefix(options.element.name);
 | 
			
		||||
 | 
			
		||||
        $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
 | 
			
		||||
            var paramName = appendModelPrefix(fieldName, prefix);
 | 
			
		||||
            value.data[paramName] = function () {
 | 
			
		||||
                var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']");
 | 
			
		||||
                // For checkboxes and radio buttons, only pick up values from checked fields.
 | 
			
		||||
                if (field.is(":checkbox")) {
 | 
			
		||||
                    return field.filter(":checked").val() || field.filter(":hidden").val() || '';
 | 
			
		||||
                }
 | 
			
		||||
                else if (field.is(":radio")) {
 | 
			
		||||
                    return field.filter(":checked").val() || '';
 | 
			
		||||
                }
 | 
			
		||||
                return field.val();
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        setValidationValues(options, "remote", value);
 | 
			
		||||
    });
 | 
			
		||||
    adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
 | 
			
		||||
        if (options.params.min) {
 | 
			
		||||
            setValidationValues(options, "minlength", options.params.min);
 | 
			
		||||
        }
 | 
			
		||||
        if (options.params.nonalphamin) {
 | 
			
		||||
            setValidationValues(options, "nonalphamin", options.params.nonalphamin);
 | 
			
		||||
        }
 | 
			
		||||
        if (options.params.regex) {
 | 
			
		||||
            setValidationValues(options, "regex", options.params.regex);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    adapters.add("fileextensions", ["extensions"], function (options) {
 | 
			
		||||
        setValidationValues(options, "extension", options.params.extensions);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $(function () {
 | 
			
		||||
        $jQval.unobtrusive.parse(document);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return $jQval.unobtrusive;
 | 
			
		||||
}));
 | 
			
		||||
							
								
								
									
										8
									
								
								MyWebApp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										22
									
								
								MyWebApp/wwwroot/lib/jquery-validation/LICENSE.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,22 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
=====================
 | 
			
		||||
 | 
			
		||||
Copyright Jörn Zaefferer
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										1158
									
								
								MyWebApp/wwwroot/lib/jquery-validation/dist/additional-methods.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4
									
								
								MyWebApp/wwwroot/lib/jquery-validation/dist/additional-methods.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1601
									
								
								MyWebApp/wwwroot/lib/jquery-validation/dist/jquery.validate.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										4
									
								
								MyWebApp/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										21
									
								
								MyWebApp/wwwroot/lib/jquery/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,21 @@
 | 
			
		||||
 | 
			
		||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
a copy of this software and associated documentation files (the
 | 
			
		||||
"Software"), to deal in the Software without restriction, including
 | 
			
		||||
without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be
 | 
			
		||||
included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
			
		||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
			
		||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
			
		||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
							
								
								
									
										10881
									
								
								MyWebApp/wwwroot/lib/jquery/dist/jquery.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										2
									
								
								MyWebApp/wwwroot/lib/jquery/dist/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								MyWebApp/wwwroot/lib/jquery/dist/jquery.min.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7
									
								
								PlaywrightTests/Folder.DotSettings.user
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,7 @@
 | 
			
		||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
 | 
			
		||||
	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=e13ade49_002D6a8c_002D4921_002Dbd1b_002Df72c82233407/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="Tests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
 | 
			
		||||
  <TestAncestor>
 | 
			
		||||
    <TestId>NUnit3x::62EE459B-FEF4-0BE8-0E30-158CFDB19555::net7.0::PlaywrightTests.GumbyPageTests</TestId>
 | 
			
		||||
    <TestId>NUnit3x::62EE459B-FEF4-0BE8-0E30-158CFDB19555::net7.0::PlaywrightTests.PokeyPageTests</TestId>
 | 
			
		||||
  </TestAncestor>
 | 
			
		||||
</SessionState></s:String></wpf:ResourceDictionary>
 | 
			
		||||
							
								
								
									
										138
									
								
								PlaywrightTests/GumbyPageTests.cs
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,138 @@
 | 
			
		||||
using NUnit.Framework;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using Microsoft.Playwright;
 | 
			
		||||
using Microsoft.Playwright.NUnit;
 | 
			
		||||
using NUnit.Framework.Internal;
 | 
			
		||||
 | 
			
		||||
namespace PlaywrightTests;
 | 
			
		||||
 | 
			
		||||
[Parallelizable(ParallelScope.Self)]
 | 
			
		||||
[TestFixture]
 | 
			
		||||
public partial class GumbyPageTests : PageTest
 | 
			
		||||
{
 | 
			
		||||
    private const string ScreenshotRoot = "../../../screenshots/";
 | 
			
		||||
    private const string HomeUrl = "http://localhost:5296";
 | 
			
		||||
    private const int AppInitDelay = 5000;
 | 
			
		||||
    private IPage? _page;
 | 
			
		||||
    private IBrowser? _browser;
 | 
			
		||||
    
 | 
			
		||||
    [GeneratedRegex("Home page")]
 | 
			
		||||
    private static partial Regex HomePageRegex();
 | 
			
		||||
    
 | 
			
		||||
    [GeneratedRegex(".*Gumby")]
 | 
			
		||||
    private static partial Regex GumbyUrlRegex();
 | 
			
		||||
 | 
			
		||||
    [SetUp]
 | 
			
		||||
    public async Task Init()
 | 
			
		||||
    {
 | 
			
		||||
        _browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions() { Headless = true, });
 | 
			
		||||
        _page = await _browser.NewPageAsync();
 | 
			
		||||
        await WaitForApp(_page);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task GumbyOptionShouldBePresentInMenu()
 | 
			
		||||
    {
 | 
			
		||||
        // Confirm we've found the Gumby link in the header
 | 
			
		||||
        var gumbyPageLink = _page!.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Gumby" });
 | 
			
		||||
        await Expect(gumbyPageLink).ToHaveAttributeAsync("href", "/Gumby");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task NavigationToGumbyPageShouldSucceed()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoGumby(_page!);
 | 
			
		||||
        await PageSnap(_page!, "gumby.png");
 | 
			
		||||
        await Expect(_page!).ToHaveURLAsync(GumbyUrlRegex());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task GumbyImageShouldBePresentOnBrowser()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoGumby(_page!);
 | 
			
		||||
        Expect(_page!.GetByRole(AriaRole.Img, new PageGetByRoleOptions { Name = "Gumby" }));
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task ResponseFromButtonShouldNotTakeTooLong()
 | 
			
		||||
    {
 | 
			
		||||
        /*
 | 
			
		||||
         * This test will sometimes pass, and sometimes fail, if the randomizer on MyWebApp is working correctly.
 | 
			
		||||
         * That is BY DESIGN. It's meant to show (at least in a rudimentary way) how a Playwright test can be used
 | 
			
		||||
         * to do synthetic monitoring. 
 | 
			
		||||
         */
 | 
			
		||||
        await GotoGumby(_page!);
 | 
			
		||||
        
 | 
			
		||||
        const int delay = 10; //MyWebApp is set to 12 seconds, so it should fail sometimes
 | 
			
		||||
        const int delayMillis = delay * 1000; // A thousand milliseconds in a second
 | 
			
		||||
        
 | 
			
		||||
        await _page!.GetByText("Clear").ClickAsync(); //clear the label first.
 | 
			
		||||
        await PageSnap(_page!, "gumby-before-button-press.png");
 | 
			
		||||
        
 | 
			
		||||
        await _page!.GetByText("Press Me!").ClickAsync();
 | 
			
		||||
        await PageSnap(_page!, "/gumby-after-button-press-during-wait.png");
 | 
			
		||||
        
 | 
			
		||||
        await Expect(_page!.Locator("label[id=result]"))
 | 
			
		||||
            .ToContainTextAsync("You Pressed The Button", new LocatorAssertionsToContainTextOptions {Timeout = delayMillis});
 | 
			
		||||
       
 | 
			
		||||
        await PageSnap(_page!, "gumby-after-test-completion.png");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*** HELPERS ***/
 | 
			
		||||
    
 | 
			
		||||
    private static async Task PageSnap(IPage page, string filename)
 | 
			
		||||
    {
 | 
			
		||||
        await page.ScreenshotAsync(new PageScreenshotOptions { FullPage = true, Path = ScreenshotRoot+"/"+filename});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static async Task ElementSnap(ILocator locator, string filename)
 | 
			
		||||
    {
 | 
			
		||||
        await locator.ScreenshotAsync(new LocatorScreenshotOptions { Path = ScreenshotRoot+"/"+filename });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static async Task GotoGumby(IPage page)
 | 
			
		||||
    {
 | 
			
		||||
        await page.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Gumby" }).ClickAsync();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static async Task WaitForApp(IPage page)
 | 
			
		||||
    {
 | 
			
		||||
        var pageIsLoaded = false;
 | 
			
		||||
        while (!pageIsLoaded)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await page.GotoAsync(HomeUrl, new PageGotoOptions() { Timeout = AppInitDelay }); 
 | 
			
		||||
                pageIsLoaded = true;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(AppInitDelay);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var appIsLoaded = false;
 | 
			
		||||
        while (!appIsLoaded)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var titleAsync = await page.TitleAsync();
 | 
			
		||||
                if (HomePageRegex().Match(titleAsync).Success)
 | 
			
		||||
                {
 | 
			
		||||
                    appIsLoaded = true;
 | 
			
		||||
                    continue;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                // _logger.Information("Error loading app");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // _logger.Information("App not loaded, delaying before retrying...");
 | 
			
		||||
            await Task.Delay(AppInitDelay);
 | 
			
		||||
        }
 | 
			
		||||
        // _logger.Information($"{nameof(WaitForApp)} completed");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								PlaywrightTests/PlaywrightTests.csproj
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,24 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <TargetFramework>net7.0</TargetFramework>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
 | 
			
		||||
    <IsPackable>false</IsPackable>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Playwright.NUnit" Version="1.28.0" />
 | 
			
		||||
    <PackageReference Include="NUnit" Version="3.13.3" />
 | 
			
		||||
    <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
 | 
			
		||||
    <PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
 | 
			
		||||
    <PackageReference Include="coverlet.collector" Version="3.1.2" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="screenshots" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										139
									
								
								PlaywrightTests/PokeyPageTests.cs
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,139 @@
 | 
			
		||||
using NUnit.Framework;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using Microsoft.Playwright;
 | 
			
		||||
using Microsoft.Playwright.NUnit;
 | 
			
		||||
using NUnit.Framework.Internal;
 | 
			
		||||
 | 
			
		||||
namespace PlaywrightTests;
 | 
			
		||||
 | 
			
		||||
[Parallelizable(ParallelScope.Self)]
 | 
			
		||||
[TestFixture]
 | 
			
		||||
public partial class PokeyPageTests : PageTest
 | 
			
		||||
{
 | 
			
		||||
    private const string ScreenshotRoot = "../../../screenshots/";
 | 
			
		||||
    private const string HomeUrl = "http://localhost:5296";
 | 
			
		||||
    private const int AppInitDelay = 5000;
 | 
			
		||||
    private IPage? _page;
 | 
			
		||||
    private IBrowser? _browser;
 | 
			
		||||
    
 | 
			
		||||
    [GeneratedRegex("Home page")]
 | 
			
		||||
    private static partial Regex HomePageRegex();
 | 
			
		||||
    
 | 
			
		||||
    [GeneratedRegex(".*Pokey")]
 | 
			
		||||
    private static partial Regex PokeyUrlRegex();
 | 
			
		||||
 | 
			
		||||
    [SetUp]
 | 
			
		||||
    public async Task Init()
 | 
			
		||||
    {
 | 
			
		||||
        _browser = await Playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions() { Headless = true, });
 | 
			
		||||
        _page = await _browser.NewPageAsync();
 | 
			
		||||
        await WaitForApp(_page);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task PokeyOptionShouldBePresentInMenu()
 | 
			
		||||
    {
 | 
			
		||||
        // Confirm we've found the Gumby link in the header
 | 
			
		||||
        var pokeyPageLink = _page!.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Pokey" });
 | 
			
		||||
        await Expect(pokeyPageLink).ToHaveAttributeAsync("href", "/Pokey");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task NavigationToPokeyPageShouldSucceed()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoPokey(_page!);
 | 
			
		||||
        await PageSnap(_page!, "gumby.png");
 | 
			
		||||
        await Expect(_page!).ToHaveURLAsync(PokeyUrlRegex());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task PokeyImageShouldBePresentOnBrowser()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoPokey(_page!);
 | 
			
		||||
        Expect(_page!.GetByRole(AriaRole.Img, new PageGetByRoleOptions { Name = "Pokey" }));
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task BothTimesShouldBeVisibleOnGet()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoPokey(_page!);
 | 
			
		||||
        var handleList = _page!.QuerySelectorAllAsync("//*[ contains(text(), 'time is' ) ]").Result;
 | 
			
		||||
        Assert.That(handleList, Has.Count.EqualTo(2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Test]
 | 
			
		||||
    public async Task BothTimesShouldMatchOnGet()
 | 
			
		||||
    {
 | 
			
		||||
        await GotoPokey(_page!);
 | 
			
		||||
        var handleList = _page!.QuerySelectorAllAsync("//*[ contains(text(), 'time is' ) ]").Result;
 | 
			
		||||
        var time1= await handleList[0].TextContentAsync();
 | 
			
		||||
        var time2 = await handleList[1].TextContentAsync();
 | 
			
		||||
     
 | 
			
		||||
        // ReSharper disable once StringIndexOfIsCultureSpecific.1
 | 
			
		||||
        var startIndex1 = time1!.IndexOf(" is ") + 4;
 | 
			
		||||
        var dateTime1 = DateTime.Parse(time1[startIndex1..]);
 | 
			
		||||
        // ReSharper disable once StringIndexOfIsCultureSpecific.1
 | 
			
		||||
        var startIndex2 = time2!.IndexOf(" is ") + 4;
 | 
			
		||||
        var dateTime2 = DateTime.Parse(time1[startIndex2..]);
 | 
			
		||||
        
 | 
			
		||||
        Assert.That(dateTime1, Is.EqualTo(dateTime2));
 | 
			
		||||
 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*** HELPERS ***/
 | 
			
		||||
    
 | 
			
		||||
    private static async Task PageSnap(IPage page, string filename)
 | 
			
		||||
    {
 | 
			
		||||
        await page.ScreenshotAsync(new PageScreenshotOptions { FullPage = true, Path = ScreenshotRoot+"/"+filename});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static async Task ElementSnap(ILocator locator, string filename)
 | 
			
		||||
    {
 | 
			
		||||
        await locator.ScreenshotAsync(new LocatorScreenshotOptions { Path = ScreenshotRoot+"/"+filename });
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static async Task GotoPokey(IPage page)
 | 
			
		||||
    {
 | 
			
		||||
        await page.GetByRole(AriaRole.Link, new PageGetByRoleOptions { Name = "Pokey" }).ClickAsync();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private static async Task WaitForApp(IPage page)
 | 
			
		||||
    {
 | 
			
		||||
        var pageIsLoaded = false;
 | 
			
		||||
        while (!pageIsLoaded)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await page.GotoAsync(HomeUrl, new PageGotoOptions() { Timeout = AppInitDelay }); 
 | 
			
		||||
                pageIsLoaded = true;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                await Task.Delay(AppInitDelay);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var appIsLoaded = false;
 | 
			
		||||
        while (!appIsLoaded)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var titleAsync = await page.TitleAsync();
 | 
			
		||||
                if (HomePageRegex().Match(titleAsync).Success)
 | 
			
		||||
                {
 | 
			
		||||
                    appIsLoaded = true;
 | 
			
		||||
                    continue;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                // _logger.Information("Error loading app");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // _logger.Information("App not loaded, delaying before retrying...");
 | 
			
		||||
            await Task.Delay(AppInitDelay);
 | 
			
		||||
        }
 | 
			
		||||
        // _logger.Information($"{nameof(WaitForApp)} completed");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								PlaywrightTests/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,33 @@
 | 
			
		||||
# PlayWright Tests
 | 
			
		||||
 | 
			
		||||
A simple test framework to experiment with PlayWright on .NET
 | 
			
		||||
 | 
			
		||||
It is designed to work in conjunction with the generic "MyWebApp" ASP.NET project, [set up here](https://bitbucket.org/gmgauthier_ecs/mywebapp). There are instructions there, on how to fire up the site locally.
 | 
			
		||||
 | 
			
		||||
### Prerequisites
 | 
			
		||||
 | 
			
		||||
Before running the tests, you will want to pre-install the webdriver binaries for the PlayWright test suite. This assumes you already have `powershell` for macOS installed.
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
$ cd ~/root/of/your/project
 | 
			
		||||
$ pwsh bin/Debug/net7.0/playwright.ps1 install
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Run
 | 
			
		||||
 | 
			
		||||
Once the ASP site is running, and your browser prerequisites are in place, then you can run these tests:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
 $ dotnet test 
 | 
			
		||||
  Determining projects to restore...
 | 
			
		||||
  All projects are up-to-date for restore.
 | 
			
		||||
  PlaywrightTests -> /Users/YOU/Projects/YOUR_PROJECTS/PlaywrightTests/bin/Debug/net7.0/PlaywrightTests.dll
 | 
			
		||||
Test run for /Users/YOU/Projects/YOUR_PROJECTS/PlaywrightTests/bin/Debug/net7.0/PlaywrightTests.dll (.NETCoreApp,Version=v7.0)
 | 
			
		||||
Microsoft (R) Test Execution Command Line Tool Version 17.4.0 (x64)
 | 
			
		||||
Copyright (c) Microsoft Corporation.  All rights reserved.
 | 
			
		||||
 | 
			
		||||
Starting test execution, please wait...
 | 
			
		||||
A total of 1 test files matched the specified pattern.
 | 
			
		||||
 | 
			
		||||
Passed!  - Failed:     0, Passed:     2, Skipped:     0, Total:     2, Duration: 2 s - PlaywrightTests.dll (net7.0)
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										1
									
								
								PlaywrightTests/Usings.cs
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
			
		||||
global using NUnit.Framework;
 | 
			
		||||
							
								
								
									
										204
									
								
								PlaywrightTests/index.html
									
									
									
									
									
										Executable file
									
								
							
							
						
						@ -0,0 +1,204 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
  <head>
 | 
			
		||||
      <meta charset="utf-8">
 | 
			
		||||
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
      <meta name="description" content="OpenPGP Keyserver">
 | 
			
		||||
 | 
			
		||||
      <title>OpenPGP Keyserver</title>
 | 
			
		||||
      <link rel="icon" href="/favicon.ico" type="image/x-icon"/>
 | 
			
		||||
      <link href="assets/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css">
 | 
			
		||||
      <style type="text/css">
 | 
			
		||||
        html,body {
 | 
			
		||||
          height: 100%;
 | 
			
		||||
        }
 | 
			
		||||
        #wrap {
 | 
			
		||||
          min-height: 100%;
 | 
			
		||||
          height: auto !important;
 | 
			
		||||
          height: 100%;
 | 
			
		||||
          margin: 0 auto -60px;
 | 
			
		||||
        }
 | 
			
		||||
        #push,#footer {
 | 
			
		||||
          height: 60px;
 | 
			
		||||
        }
 | 
			
		||||
        #footer {
 | 
			
		||||
          background-color: #f5f5f5;
 | 
			
		||||
        }
 | 
			
		||||
        .container .credit {
 | 
			
		||||
            margin: 20px 0;
 | 
			
		||||
        }
 | 
			
		||||
        .modal:target {
 | 
			
		||||
            display: block;
 | 
			
		||||
        }
 | 
			
		||||
    </style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <div id="wrap">
 | 
			
		||||
      <div class="container">
 | 
			
		||||
        <div class="page-header" id="banner" style="border-bottom: 0px;">
 | 
			
		||||
          <div class="row">
 | 
			
		||||
            <div class="col-lg-12">
 | 
			
		||||
              <h1 class="text-center"><strong>Hockeypuck</strong> OpenPGP keyserver</h1>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div><!--closing page header container-->
 | 
			
		||||
      <div class="container">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
          <div class="col-lg-8 col-lg-offset-2">
 | 
			
		||||
            <form action="/pks/lookup" method="get" class="form" role="form">
 | 
			
		||||
              <div class="control-group">
 | 
			
		||||
                <div class="controls" style="max-width:30em; margin:0 auto;">
 | 
			
		||||
                  <input name="search" class="form-control" type="text" placeholder="Search for an OpenPGP Public Key, ie 0x..." style="font-size: 1.5em; line-height: 1.5em; height: 2em;" required autofocus />
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="control-group text-center" style="margin-top: 0.5em;">
 | 
			
		||||
                <div class="controls">
 | 
			
		||||
                  <button type="submit" class="btn btn-primary">
 | 
			
		||||
                    <span class="glyphicon glyphicon-search"></span>
 | 
			
		||||
                    Search Key
 | 
			
		||||
                  </button>
 | 
			
		||||
                  <a id="showSubmitFormBtn" type="button" class="btn btn-primary" data-toggle="modal" href="#submitKey">
 | 
			
		||||
                    <span class="glyphicon glyphicon-cloud-upload"></span>
 | 
			
		||||
                    Submit Key
 | 
			
		||||
                  </a>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <details class="text-center" style="margin-top: 0.5em;">
 | 
			
		||||
                <summary>Advanced Options</summary>
 | 
			
		||||
                <div class="control-group col-md-4 col-md-offset-2">
 | 
			
		||||
                  <div class="controls">
 | 
			
		||||
                    Index Options:
 | 
			
		||||
                    <label class="checkbox" for="fingerprint">
 | 
			
		||||
                      <input id="fingerprint" type="checkbox" name="fingerprint" checked="checked" />
 | 
			
		||||
                      Show OpenPGP fingerprints
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="checkbox" for="hash">
 | 
			
		||||
                      <input id="hash" type="checkbox" name="hash" />
 | 
			
		||||
                      Show full-key hashes
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="checkbox" for="exact">
 | 
			
		||||
                      <input id="exact" type="checkbox" name="exact" value="on" />
 | 
			
		||||
                      Only return exact matches
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="checkbox" for="mr">
 | 
			
		||||
                      <input id="mr" type="checkbox" name="options" value="mr" />
 | 
			
		||||
                      Machine readable
 | 
			
		||||
                    </label>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="control-group col-md-offset-6">
 | 
			
		||||
                  <div class="controls">
 | 
			
		||||
                    Index type:
 | 
			
		||||
                    <label class="radio" for="radios-0">
 | 
			
		||||
                      <input name="op" id="radios-0" value="index" checked="checked" type="radio">
 | 
			
		||||
                      Get regular index of matching keys
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="radio" for="radios-1">
 | 
			
		||||
                      <input name="op" id="radios-1" value="vindex" type="radio">
 | 
			
		||||
                      Get <strong>verbose</strong> index of matching keys
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="radio" for="radios-2">
 | 
			
		||||
                      <input name="op" id="radios-2" value="get" type="radio">
 | 
			
		||||
                      Retrieve ASCII-armored keys
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <label class="radio" for="radios-3">
 | 
			
		||||
                      <input name="op" id="radios-3" value="hget" type="radio">
 | 
			
		||||
                      Retrieve keys by full hash fingerprint
 | 
			
		||||
                    </label>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </details>
 | 
			
		||||
            </form>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="modal" id="submitKey" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
 | 
			
		||||
        <div class="modal-dialog">
 | 
			
		||||
          <div class="modal-content">
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
              <h4 class="modal-title" id="myModalLabel">Submit Your OpenPGP Public Key</h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body">
 | 
			
		||||
              <form action="/pks/add" method="post" id="keySubmitForm">
 | 
			
		||||
                <div class="control-group">
 | 
			
		||||
                  <div class="controls">
 | 
			
		||||
                    <textarea id="textarea" name="keytext" rows="20" style="width: 100%;font-family:Courier;font-size:12px;" placeholder="Enter your ASCII-armored OpenPGP public key here" required ></textarea>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="modal-footer">
 | 
			
		||||
                  <a href="#" type="button" class="btn btn-default" data-dismiss="modal">Close</a>
 | 
			
		||||
                  <button type="submit" class="btn btn-primary">
 | 
			
		||||
                    <span class="glyphicon glyphicon-cloud-upload"></span>
 | 
			
		||||
                    Submit Public Key
 | 
			
		||||
                  </button>
 | 
			
		||||
                </div>
 | 
			
		||||
              </form>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="modal" id="about" tabindex="-1" role="dialog" aria-labelledby="AboutLabel" aria-hidden="true">
 | 
			
		||||
        <div class="modal-dialog">
 | 
			
		||||
          <div class="modal-content">
 | 
			
		||||
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
              <a href="#" type="button" class="close" data-dismiss="modal" aria-hidden="true">×</a>
 | 
			
		||||
              <h4 class="modal-title" id="AboutLabel">About this Server</h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body">
 | 
			
		||||
              <p>This is an <a href="https://en.wikipedia.org/wiki/Key_server_%28cryptographic%29" target="_blank">OpenPGP keyserver</a>.</p>
 | 
			
		||||
              <p>It is provided to the community as a public service to help distribute OpenPGP encryption keys.</p>
 | 
			
		||||
              <p>Queries about the operation of this service should be directed to the server contact listed on the <a href="/pks/lookup?op=stats">statistics page</a>.</p>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
              <a href="#" type="button" class="close" data-dismiss="modal" aria-hidden="true">×</a>
 | 
			
		||||
              <h4 class="modal-title" id="AboutLabel">The Software</h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body">
 | 
			
		||||
              <p>This server is powered by the open-source keyserver software <a href="https://hockeypuck.io" target="_blank">Hockeypuck</a>.
 | 
			
		||||
                Hockeypuck is a <em>synchronising</em> keyserver that acts as part of a
 | 
			
		||||
                <a href="https://spider.pgpkeys.eu" target="_blank">decentralised networked database</a> for OpenPGP public keys.</p>
 | 
			
		||||
              <p>To report a bug in the Hockeypuck software, or contribute to its development, please visit the
 | 
			
		||||
                <a href="https://github.com/hockeypuck/hockeypuck" target="_blank">Hockeypuck project on GitHub</a>.</p>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
              <a href="#" type="button" class="close" data-dismiss="modal" aria-hidden="true">×</a>
 | 
			
		||||
              <h4 class="modal-title" id="AboutLabel">The OpenPGP Standard</h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body">
 | 
			
		||||
              <p><strong>OpenPGP</strong> is an <a href="https://en.wikipedia.org/wiki/End-to-end_encryption" target="_blank">End-to-End encryption</a> standard.
 | 
			
		||||
                It allows emails, files and other data to be encrypted so that they cannot be read by a third party,
 | 
			
		||||
                and/or signed so that they cannot be modified, while in transit between the sender and recipient.
 | 
			
		||||
                It is used primarily for high-latency and long-timescale applications such as email, software distribution, record archival and backups.</p>
 | 
			
		||||
              <ul>
 | 
			
		||||
                <li><a href="https://en.wikipedia.org/wiki/Pretty_Good_Privacy" target="_blank">PGP (Wikipedia)</a></li>
 | 
			
		||||
                <li><a href="https://emailselfdefense.fsf.org/en/" target="_blank">Email Self-defense (Free Software Foundation)</a></li>
 | 
			
		||||
                <li><a href="https://gnupg.org/" target="_blank">GnuPG Homepage</a></li>
 | 
			
		||||
                <li><a href="https://sequoia-pgp.org/" target="_blank">Sequoia PGP Homepage</a></li>
 | 
			
		||||
              </ul>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div><!--Closing content wrap-->
 | 
			
		||||
    <div id="footer">
 | 
			
		||||
      <div class="container">
 | 
			
		||||
        <div style="max-width: 20em; float: left;" >
 | 
			
		||||
          <p class="muted credit small">
 | 
			
		||||
            <a href="#about">about</a> |
 | 
			
		||||
            <a href="/pks/lookup?op=stats">statistics</a>
 | 
			
		||||
          </p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div style="float:right;">
 | 
			
		||||
      <!--
 | 
			
		||||
          <p class="muted credit small">Use our Tor hidden service at <a href="${TOR_URL}">${TOR_URL}</a>.</p>
 | 
			
		||||
      -->
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 71 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								PlaywrightTests/screenshots/gumby-after-test-completion.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 75 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								PlaywrightTests/screenshots/gumby-before-button-press.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 72 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								PlaywrightTests/screenshots/gumby.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 87 KiB  |