Refactor project structure in solution
Replaced "EnvelopeGenerator.WebUI" with "EnvelopeGenerator.Server" and "EnvelopeGenerator.WebUI.Client" with "EnvelopeGenerator.Server.Client". Updated project entries, solution configuration platforms, and nested projects to reflect these changes.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
@page "/sender"
|
||||
@rendermode InteractiveWebAssembly
|
||||
|
||||
<h3>EnvelopeSender</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
@page "/"
|
||||
@rendermode InteractiveWebAssembly
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
|
||||
<div class="home-page-wrapper">
|
||||
|
||||
<div class="home-hero-header">
|
||||
<div class="home-hero-header__inner">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="home-hero-header__icon" viewBox="0 0 16 16">
|
||||
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<h1 class="home-hero-header__title">SignFlow</h1>
|
||||
<p class="home-hero-header__subtitle">Willkommen im eSign-Portal</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="home-content">
|
||||
<div class="home-card card shadow border-0">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
|
||||
<p class="text-muted mb-4" style="font-size: 0.92rem; line-height: 1.7; text-align: justify; text-align-last: left; min-height: calc(0.92rem * 1.7 * 9);">
|
||||
<span id="home-description"></span>
|
||||
</p>
|
||||
|
||||
<div class="mt-4 pt-3 border-top">
|
||||
<div class="d-flex flex-wrap justify-content-center gap-3">
|
||||
<div class="home-feature-badge">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="currentColor" class="me-1" viewBox="0 0 16 16">
|
||||
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/>
|
||||
</svg>
|
||||
Sicherer Zugang
|
||||
</div>
|
||||
<div class="home-feature-badge">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="currentColor" class="me-1" viewBox="0 0 16 16">
|
||||
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
|
||||
</svg>
|
||||
Digitale Unterschrift
|
||||
</div>
|
||||
<div class="home-feature-badge">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="currentColor" class="me-1" viewBox="0 0 16 16">
|
||||
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
|
||||
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
|
||||
</svg>
|
||||
PDF-Export
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private const string HomePageDescription =
|
||||
"Das digitale Unterschriftenportal ist eine Plattform, die entwickelt wurde, um Ihre Dokumente sicher zu unterschreiben und zu verwalten. " +
|
||||
"Mit seiner benutzerfreundlichen Oberfläche können Sie Ihre Dokumente schnell hochladen, die Unterschriftsprozesse verfolgen und Ihre digitalen Unterschriftenanwendungen einfach durchführen. " +
|
||||
"Dieses Portal beschleunigt Ihren Arbeitsablauf mit rechtlich gültigen Unterschriften und erhöht gleichzeitig die Sicherheit Ihrer Dokumente.";
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await JS.InvokeVoidAsync("receiverSignature.startTyped", "home-description", HomePageDescription, 15);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
@page "/envelope/login/{EnvelopeKey}"
|
||||
@rendermode InteractiveWebAssembly
|
||||
@using EnvelopeGenerator.WebUI.Client.Services
|
||||
@inject AuthService AuthService
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
|
||||
<div class="login-page-wrapper d-flex align-items-center justify-content-center min-vh-100">
|
||||
<div class="login-card card shadow border-0" style="max-width: 440px; width: 100%;">
|
||||
|
||||
<div class="card-header text-white text-center py-4 border-0" style="background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%); border-radius: calc(0.375rem - 1px) calc(0.375rem - 1px) 0 0;">
|
||||
<div class="mb-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h5 class="mb-0 fw-semibold">Dokument öffnen</h5>
|
||||
<p class="mb-0 mt-1 opacity-75" style="font-size: 0.85rem;">Sicherer Zugang mit Zugangscode</p>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4">
|
||||
|
||||
<p class="text-muted mb-4" style="font-size: 0.875rem; line-height: 1.5;">
|
||||
Bitte geben Sie den Zugangscode ein, den Sie per E-Mail erhalten haben, um das Dokument sicher zu öffnen.
|
||||
</p>
|
||||
|
||||
@if (LoginResult == EnvelopeLoginResult.NotFound) {
|
||||
<div class="alert alert-warning d-flex align-items-start gap-2 py-2" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="flex-shrink-0 mt-1" viewBox="0 0 16 16">
|
||||
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Dokument nicht gefunden.</strong><br />
|
||||
<span style="font-size:0.85rem;">Der angegebene Zugangscode konnte keinem Dokument zugeordnet werden. Bitte prüfen Sie den Link in Ihrer E-Mail.</span>
|
||||
</div>
|
||||
</div>
|
||||
} else if (LoginResult == EnvelopeLoginResult.InvalidCode) {
|
||||
<div class="alert alert-danger d-flex align-items-start gap-2 py-2" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="flex-shrink-0 mt-1" viewBox="0 0 16 16">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Ungültiger Zugangscode.</strong><br />
|
||||
<span style="font-size:0.85rem;">Der eingegebene Code ist falsch. Bitte versuchen Sie es erneut.</span>
|
||||
</div>
|
||||
</div>
|
||||
} else if (LoginResult == EnvelopeLoginResult.Error) {
|
||||
<div class="alert alert-secondary d-flex align-items-start gap-2 py-2" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="flex-shrink-0 mt-1" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Serverfehler.</strong><br />
|
||||
<span style="font-size:0.85rem;">Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-medium" for="login-access-code">
|
||||
Zugangscode
|
||||
<span class="text-danger ms-1">*</span>
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#6c757d" viewBox="0 0 16 16">
|
||||
<path d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1.837 1.337A3.5 3.5 0 0 1 3.5 11.5zm0-1a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input id="login-access-code"
|
||||
type="@(ShowCode ? "text" : "password")"
|
||||
class="form-control border-start-0 border-end-0 @(LoginResult == EnvelopeLoginResult.InvalidCode ? "is-invalid" : null)"
|
||||
placeholder="Zugangscode eingeben"
|
||||
@bind="AccessCode"
|
||||
@bind:event="oninput"
|
||||
@onkeydown="OnKeyDownAsync"
|
||||
disabled="@IsLoading"
|
||||
autocomplete="one-time-code" />
|
||||
<button type="button"
|
||||
class="btn btn-outline-secondary border-start-0"
|
||||
style="border-left: none;"
|
||||
tabindex="-1"
|
||||
@onclick="() => ShowCode = !ShowCode">
|
||||
@if (ShowCode) {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/>
|
||||
<path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/>
|
||||
<path d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709z"/>
|
||||
<path fill-rule="evenodd" d="M13.646 14.354l-12-12 .708-.708 12 12-.708.708z"/>
|
||||
</svg>
|
||||
} else {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
|
||||
<path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
|
||||
</svg>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary w-100 py-2 fw-medium"
|
||||
style="background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%); border: none;"
|
||||
@onclick="SubmitAsync"
|
||||
disabled="@(IsLoading || string.IsNullOrWhiteSpace(AccessCode))">
|
||||
@if (IsLoading) {
|
||||
<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
|
||||
<span>Überprüfen …</span>
|
||||
} else {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="me-2" viewBox="0 0 16 16">
|
||||
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/>
|
||||
</svg>
|
||||
<span>Dokument öffnen</span>
|
||||
}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer text-center text-muted py-3 border-0 bg-transparent" style="font-size: 0.78rem;">
|
||||
Bei Problemen wenden Sie sich bitte an den Absender des Dokuments.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public string EnvelopeKey { get; set; } = string.Empty;
|
||||
|
||||
string AccessCode = string.Empty;
|
||||
bool ShowCode;
|
||||
bool IsLoading;
|
||||
EnvelopeLoginResult? LoginResult;
|
||||
|
||||
async Task OnKeyDownAsync(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs e) {
|
||||
if (e.Key == "Enter")
|
||||
await SubmitAsync();
|
||||
}
|
||||
|
||||
async Task SubmitAsync() {
|
||||
if (string.IsNullOrWhiteSpace(AccessCode) || IsLoading) return;
|
||||
|
||||
IsLoading = true;
|
||||
LoginResult = null;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
var result = await AuthService.LoginEnvelopeReceiverAsync(EnvelopeKey, AccessCode.Trim());
|
||||
|
||||
if (result == EnvelopeLoginResult.Success) {
|
||||
Navigation.NavigateTo($"/envelope/{Uri.EscapeDataString(EnvelopeKey)}", forceLoad: true);
|
||||
return;
|
||||
}
|
||||
|
||||
LoginResult = result;
|
||||
IsLoading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
@page "/sender/login"
|
||||
@rendermode InteractiveWebAssembly
|
||||
@using EnvelopeGenerator.WebUI.Client.Services
|
||||
@inject AuthService AuthService
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
|
||||
<div class="login-page-wrapper d-flex align-items-center justify-content-center min-vh-100">
|
||||
<div class="login-card card shadow border-0" style="max-width: 440px; width: 100%;">
|
||||
|
||||
<div class="card-header text-white text-center py-4 border-0" style="background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%); border-radius: calc(0.375rem - 1px) calc(0.375rem - 1px) 0 0;">
|
||||
<div class="mb-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
|
||||
<path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h5 class="mb-0 fw-semibold">Sender Anmeldung</h5>
|
||||
<p class="mb-0 mt-1 opacity-75" style="font-size: 0.85rem;">Sicherer Zugang zum Sender-Dashboard</p>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4">
|
||||
|
||||
<p class="text-muted mb-4" style="font-size: 0.875rem; line-height: 1.5;">
|
||||
Bitte melden Sie sich mit Ihren Zugangsdaten an, um auf das Sender-Dashboard zuzugreifen.
|
||||
</p>
|
||||
|
||||
@if (LoginResult == SenderLoginResult.InvalidCredentials) {
|
||||
<div class="alert alert-danger d-flex align-items-start gap-2 py-2" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="flex-shrink-0 mt-1" viewBox="0 0 16 16">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Ungültige Anmeldedaten.</strong><br />
|
||||
<span style="font-size:0.85rem;">Benutzername oder Passwort ist falsch. Bitte versuchen Sie es erneut.</span>
|
||||
</div>
|
||||
</div>
|
||||
} else if (LoginResult == SenderLoginResult.Error) {
|
||||
<div class="alert alert-secondary d-flex align-items-start gap-2 py-2" role="alert">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="flex-shrink-0 mt-1" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Serverfehler.</strong><br />
|
||||
<span style="font-size:0.85rem;">Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-medium" for="login-username">
|
||||
Benutzername
|
||||
<span class="text-danger ms-1">*</span>
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#6c757d" viewBox="0 0 16 16">
|
||||
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3Zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input id="login-username"
|
||||
type="text"
|
||||
class="form-control @(LoginResult == SenderLoginResult.InvalidCredentials ? "is-invalid" : null)"
|
||||
placeholder="Benutzername eingeben"
|
||||
@bind="Username"
|
||||
@bind:event="oninput"
|
||||
@onkeydown="OnKeyDownAsync"
|
||||
disabled="@IsLoading"
|
||||
autocomplete="username" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-medium" for="login-password">
|
||||
Passwort
|
||||
<span class="text-danger ms-1">*</span>
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#6c757d" viewBox="0 0 16 16">
|
||||
<path d="M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<input id="login-password"
|
||||
type="@(ShowPassword ? "text" : "password")"
|
||||
class="form-control border-start-0 border-end-0 @(LoginResult == SenderLoginResult.InvalidCredentials ? "is-invalid" : null)"
|
||||
placeholder="Passwort eingeben"
|
||||
@bind="Password"
|
||||
@bind:event="oninput"
|
||||
@onkeydown="OnKeyDownAsync"
|
||||
disabled="@IsLoading"
|
||||
autocomplete="current-password" />
|
||||
<button type="button"
|
||||
class="btn btn-outline-secondary border-start-0"
|
||||
style="border-left: none;"
|
||||
tabindex="-1"
|
||||
@onclick="() => ShowPassword = !ShowPassword">
|
||||
@if (ShowPassword) {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/>
|
||||
<path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/>
|
||||
<path d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709z"/>
|
||||
<path fill-rule="evenodd" d="M13.646 14.354l-12-12 .708-.708 12 12-.708.708z"/>
|
||||
</svg>
|
||||
} else {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
|
||||
<path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
|
||||
</svg>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary w-100 py-2 fw-medium"
|
||||
style="background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%); border: none;"
|
||||
@onclick="SubmitAsync"
|
||||
disabled="@(IsLoading || string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password))">
|
||||
@if (IsLoading) {
|
||||
<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
|
||||
<span>Anmelden …</span>
|
||||
} else {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="me-2" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0v-2z"/>
|
||||
<path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
|
||||
</svg>
|
||||
<span>Anmelden</span>
|
||||
}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer text-center text-muted py-3 border-0 bg-transparent" style="font-size: 0.78rem;">
|
||||
Bei Problemen wenden Sie sich bitte an den Administrator.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
string Username = string.Empty;
|
||||
string Password = string.Empty;
|
||||
bool ShowPassword;
|
||||
bool IsLoading;
|
||||
SenderLoginResult? LoginResult;
|
||||
|
||||
async Task OnKeyDownAsync(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs e) {
|
||||
if (e.Key == "Enter")
|
||||
await SubmitAsync();
|
||||
}
|
||||
|
||||
async Task SubmitAsync() {
|
||||
if (string.IsNullOrWhiteSpace(Username) || string.IsNullOrWhiteSpace(Password) || IsLoading) return;
|
||||
|
||||
IsLoading = true;
|
||||
LoginResult = null;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
var result = await AuthService.LoginSenderAsync(Username.Trim(), Password.Trim());
|
||||
|
||||
if (result == SenderLoginResult.Success) {
|
||||
Navigation.NavigateTo("/sender", forceLoad: true);
|
||||
return;
|
||||
}
|
||||
|
||||
LoginResult = result;
|
||||
IsLoading = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user