mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-05-07 23:05:40 -04:00
Merge pull request #22 from lanedirt/21-improve-blazor-wasm-ui
Improve blazor wasm UI
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400" role="alert">
|
||||
<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400 border-2" role="alert">
|
||||
@Message
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
<div class="p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400" role="alert">
|
||||
<div class="p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400 border-2" role="alert">
|
||||
@Message
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
@inject GlobalNotificationService GlobalNotificationService
|
||||
@implements IDisposable
|
||||
|
||||
@foreach (var message in Messages)
|
||||
{
|
||||
if (message.Key == "success")
|
||||
{
|
||||
<AlertMessageSuccess Message="@message.Value" />
|
||||
}
|
||||
}
|
||||
@foreach (var message in Messages)
|
||||
{
|
||||
if (message.Key == "error")
|
||||
{
|
||||
<AlertMessageError Message="@message.Value" />
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<KeyValuePair<string, string>> Messages { get; set; } = new();
|
||||
private bool _onChangeSubscribed = false;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender)
|
||||
{
|
||||
// We subscribe to the OnChange event of the PortalMessageService to update the UI when a new message is added
|
||||
RefreshAddMessages();
|
||||
GlobalNotificationService.OnChange += RefreshAddMessages;
|
||||
_onChangeSubscribed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
// We unsubscribe from the OnChange event of the PortalMessageService when the component is disposed
|
||||
if (_onChangeSubscribed)
|
||||
{
|
||||
GlobalNotificationService.OnChange -= RefreshAddMessages;
|
||||
_onChangeSubscribed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the messages by adding any new messages from the PortalMessageService.
|
||||
/// </summary>
|
||||
public void RefreshAddMessages()
|
||||
{
|
||||
// We retrieve any additional messages from the GlobalNotificationService that we do not yet have.
|
||||
var newMessages = GlobalNotificationService.GetMessagesForDisplay();
|
||||
foreach (var message in newMessages)
|
||||
{
|
||||
if (!Messages.Any(m => m.Key == message.Key && m.Value == message.Value))
|
||||
{
|
||||
Messages.Add(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove messages that are no longer in the GlobalNotificationService and have already been displayed.
|
||||
var messagesToRemove = Messages.Where(m => !newMessages.Any(nm => nm.Key == m.Key && nm.Value == m.Value)).ToList();
|
||||
foreach (var message in messagesToRemove)
|
||||
{
|
||||
Messages.Remove(message);
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
@using AliasVault.WebApp.Components.Models
|
||||
@inherits ComponentBase
|
||||
@using Microsoft.IdentityModel.Tokens
|
||||
@inherits ComponentBase
|
||||
|
||||
<nav class="flex mb-5" aria-label="RecentEmails">
|
||||
<ol class="inline-flex items-center space-x-1 text-sm font-medium md:space-x-2">
|
||||
@@ -33,11 +32,16 @@
|
||||
}
|
||||
</ol>
|
||||
</nav>
|
||||
<GlobalNotificationDisplay />
|
||||
|
||||
@code {
|
||||
/// <summary>
|
||||
/// Gets or sets the list of breadcrumb items.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<BreadcrumbItem> BreadcrumbItems { get; set; } = new List<BreadcrumbItem>();
|
||||
public List<BreadcrumbItem> BreadcrumbItems { get; set; } = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
@page "/add-alias"
|
||||
@page "/alias/{id:guid}/edit"
|
||||
|
||||
@inherits PageBase
|
||||
@inject NavigationManager Navigation
|
||||
@inject AliasService AliasService
|
||||
@inherits PageBase
|
||||
@using AliasGenerators.Implementations
|
||||
@using AliasGenerators.Password.Implementations
|
||||
@using AliasVault.Shared.Models.WebApi
|
||||
@using AliasVault.WebApp.Services
|
||||
|
||||
@if (EditMode)
|
||||
{
|
||||
@@ -197,7 +195,9 @@ else
|
||||
{
|
||||
if (Id is null)
|
||||
{
|
||||
Navigation.NavigateTo("/404");
|
||||
// Error loading alias.
|
||||
GlobalNotificationService.AddErrorMessage("This alias does not exist (anymore). Please try again.");
|
||||
NavigationManager.NavigateTo("/", false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,9 @@ else
|
||||
var alias = await AliasService.LoadAliasAsync(Id.Value);
|
||||
if (alias is null)
|
||||
{
|
||||
Navigation.NavigateTo("/404");
|
||||
// Error loading alias.
|
||||
GlobalNotificationService.AddErrorMessage("This alias does not exist (anymore). Please try again.");
|
||||
NavigationManager.NavigateTo("/", false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -295,7 +297,7 @@ else
|
||||
{
|
||||
if (Id is not null)
|
||||
{
|
||||
await AliasService.UpdateAliasAsync(Obj, Id.Value);
|
||||
Id = await AliasService.UpdateAliasAsync(Obj, Id.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -306,12 +308,23 @@ else
|
||||
IsSaving = false;
|
||||
StateHasChanged();
|
||||
|
||||
if (Id == Guid.Empty)
|
||||
if (Id is null || Id == Guid.Empty)
|
||||
{
|
||||
// Error saving, do not navigate.
|
||||
// Error saving.
|
||||
GlobalNotificationService.AddErrorMessage("Error saving alias. Please try again.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
// No error, add success message.
|
||||
if (EditMode)
|
||||
{
|
||||
GlobalNotificationService.AddSuccessMessage("Alias updated successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalNotificationService.AddSuccessMessage("Alias created successfully.");
|
||||
}
|
||||
|
||||
Navigation.NavigateTo("/alias/" + Id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
@page "/alias/{id:guid}/delete"
|
||||
|
||||
@using AliasVault.Shared.Models.WebApi
|
||||
@using AliasVault.WebApp.Services
|
||||
@inherits PageBase
|
||||
@using AliasVault.Shared.Models.WebApi
|
||||
@inject AliasService AliasService
|
||||
|
||||
<LayoutPageTitle>Delete alias</LayoutPageTitle>
|
||||
@@ -82,10 +80,12 @@ else
|
||||
{
|
||||
if (Obj is null)
|
||||
{
|
||||
GlobalNotificationService.AddErrorMessage("Error deleting. Alias not found.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
await AliasService.DeleteAliasAsync(Id);
|
||||
GlobalNotificationService.AddSuccessMessage("Alias successfully deleted.");
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@page "/alias/{id:guid}"
|
||||
@inherits PageBase
|
||||
@using AliasVault.Shared.Models.WebApi
|
||||
@using AliasVault.WebApp.Services
|
||||
@using AliasVault.WebApp.Components.Email
|
||||
@inject AliasService AliasService
|
||||
@inherits PageBase
|
||||
|
||||
<LayoutPageTitle>View alias</LayoutPageTitle>
|
||||
|
||||
@@ -13,9 +12,11 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<div class="grid grid-cols-2 px-4 pt-6 md:grid-cols-3 lg:gap-4 dark:bg-gray-900">
|
||||
<div class="mb-4 col-span-full xl:mb-2">
|
||||
<Breadcrumb BreadcrumbItems="BreadcrumbItems"/>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">View alias</h1>
|
||||
<div class="flex">
|
||||
@@ -28,6 +29,7 @@ else
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Content -->
|
||||
<div class="col-span-full lg:col-auto">
|
||||
<div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
|
||||
@@ -144,6 +146,15 @@ else
|
||||
|
||||
// Load the aliases from the webapi via AliasService.
|
||||
Alias = await AliasService.LoadAliasAsync(Id);
|
||||
|
||||
if (Alias is null)
|
||||
{
|
||||
// Error loading alias.
|
||||
GlobalNotificationService.AddErrorMessage("This alias does not exist (anymore). Please try again.");
|
||||
NavigationManager.NavigateTo("/", false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
AliasEmail = Alias?.Identity.EmailPrefix + "@landmail.nl";
|
||||
|
||||
IsLoading = false;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
namespace AliasVault.WebApp.Pages.Base;
|
||||
|
||||
using AliasVault.WebApp.Components.Models;
|
||||
using AliasVault.WebApp.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -33,6 +34,12 @@ public class PageBase : OwningComponentBase
|
||||
[Inject]
|
||||
public AuthenticationStateProvider AuthStateProvider { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the GlobalNotificationService.
|
||||
/// </summary>
|
||||
[Inject]
|
||||
public GlobalNotificationService GlobalNotificationService { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IJSRuntime.
|
||||
/// </summary>
|
||||
@@ -55,10 +62,6 @@ public class PageBase : OwningComponentBase
|
||||
|
||||
// Add base breadcrumbs
|
||||
BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Home", Url = NavigationManager.BaseUri });
|
||||
|
||||
// Detect success messages in query string and add them to the SuccessMessages list
|
||||
// TODO: Implement this with example for default add/edit update action...
|
||||
var uri = new Uri(NavigationManager.Uri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@page "/"
|
||||
@page "/aliases"
|
||||
@using AliasVault.WebApp.Components.Alias
|
||||
@using AliasVault.WebApp.Services
|
||||
@inject AliasService AliasService
|
||||
@inherits PageBase
|
||||
@using AliasVault.WebApp.Components.Alias
|
||||
@inject AliasService AliasService
|
||||
|
||||
<LayoutPageTitle>Home</LayoutPageTitle>
|
||||
|
||||
@@ -22,13 +21,13 @@
|
||||
|
||||
@if (IsLoading)
|
||||
{
|
||||
<LoadingIndicator />
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
<div class="grid gap-4 px-4 mb-4 md:grid-cols-4 xl:grid-cols-6">
|
||||
@foreach (var alias in Aliases)
|
||||
{
|
||||
<Alias Obj="@alias"/>
|
||||
<Alias Obj="@alias"/>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -55,8 +54,7 @@
|
||||
if (aliasListEntries is null)
|
||||
{
|
||||
// Error loading aliases.
|
||||
IsLoading = false;
|
||||
StateHasChanged();
|
||||
GlobalNotificationService.AddErrorMessage("Failed to load aliases.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ builder.Services.AddTransient<AliasVaultApiHandlerService>();
|
||||
builder.Services.AddScoped<AuthService>();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, AuthStateProvider>();
|
||||
builder.Services.AddScoped<AliasService>();
|
||||
builder.Services.AddScoped<GlobalNotificationService>();
|
||||
builder.Services.AddSingleton<ClipboardCopyService>();
|
||||
builder.Services.AddAuthorizationCore();
|
||||
builder.Services.AddBlazoredLocalStorage();
|
||||
|
||||
@@ -97,7 +97,7 @@ public class AliasService(HttpClient httpClient)
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new List<AliasListEntry>();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
94
src/AliasVault.WebApp/Services/GlobalNotificationService.cs
Normal file
94
src/AliasVault.WebApp/Services/GlobalNotificationService.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// <copyright file="GlobalNotificationService.cs" company="lanedirt">
|
||||
// Copyright (c) lanedirt. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
|
||||
// </copyright>
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace AliasVault.WebApp.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Handles global notifications that should be displayed to the user, such as success or error messages. These messages
|
||||
/// are stored in this object which is scoped to the current session. This allows the messages to be cached until
|
||||
/// they actually have been displayed. So they can survive redirects and page reloads.
|
||||
/// </summary>
|
||||
public class GlobalNotificationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Allow other components to subscribe to changes in the event object.
|
||||
/// </summary>
|
||||
public event Action? OnChange;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets success messages that should be displayed to the user.
|
||||
/// </summary>
|
||||
protected List<string> SuccessMessages { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets error messages that should be displayed to the user.
|
||||
/// </summary>
|
||||
protected List<string> ErrorMessages { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a success message to the list of messages that should be displayed to the user.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to add.</param>
|
||||
/// <param name="notifyStateChanged">Whether to notify state change to subscribers. Defaults to false.
|
||||
/// Set this to true if you want to show the added message instantly instead of waiting for the notification
|
||||
/// display to rerender (e.g. after navigation).</param>
|
||||
public void AddSuccessMessage(string message, bool notifyStateChanged = false)
|
||||
{
|
||||
SuccessMessages.Add(message);
|
||||
|
||||
// Notify subscribers that a message has been added.
|
||||
if (notifyStateChanged)
|
||||
{
|
||||
NotifyStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an error message to the list of messages that should be displayed to the user.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to add.</param>
|
||||
/// <param name="notifyStateChanged">Whether to notify state change to subscribers. Defaults to false.
|
||||
/// Set this to true if you want to show the added message instantly instead of waiting for the notification
|
||||
/// display to rerender (e.g. after navigation).</param>
|
||||
public void AddErrorMessage(string message, bool notifyStateChanged = false)
|
||||
{
|
||||
ErrorMessages.Add(message);
|
||||
|
||||
// Notify subscribers that a message has been added.
|
||||
if (notifyStateChanged)
|
||||
{
|
||||
NotifyStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a dictionary with messages that should be displayed to the user. After this method is called,
|
||||
/// the messages are automatically cleared.
|
||||
/// </summary>
|
||||
/// <returns>Dictionary with messages that are ready to be displayed on the next page load.</returns>
|
||||
public List<KeyValuePair<string, string>> GetMessagesForDisplay()
|
||||
{
|
||||
var messages = new List<KeyValuePair<string, string>>();
|
||||
foreach (var message in SuccessMessages)
|
||||
{
|
||||
messages.Add(new KeyValuePair<string, string>("success", message));
|
||||
}
|
||||
|
||||
foreach (var message in ErrorMessages)
|
||||
{
|
||||
messages.Add(new KeyValuePair<string, string>("error", message));
|
||||
}
|
||||
|
||||
// Clear messages
|
||||
SuccessMessages.Clear();
|
||||
ErrorMessages.Clear();
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
private void NotifyStateChanged() => OnChange?.Invoke();
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
@using AliasVault.WebApp.Components.Alerts
|
||||
@using AliasVault.WebApp.Components.Loading
|
||||
@using AliasVault.WebApp.Pages.Base
|
||||
@using AliasVault.WebApp.Services
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||
@using Blazored.LocalStorage
|
||||
|
||||
@@ -714,10 +714,6 @@ video {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.me-2 {
|
||||
margin-inline-end: 0.5rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
@@ -770,10 +766,6 @@ video {
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.h-7 {
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
.h-8 {
|
||||
height: 2rem;
|
||||
}
|
||||
@@ -786,10 +778,6 @@ video {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.h-3 {
|
||||
height: 0.75rem;
|
||||
}
|
||||
|
||||
.w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
@@ -822,10 +810,6 @@ video {
|
||||
width: 16rem;
|
||||
}
|
||||
|
||||
.w-7 {
|
||||
width: 1.75rem;
|
||||
}
|
||||
|
||||
.w-8 {
|
||||
width: 2rem;
|
||||
}
|
||||
@@ -834,10 +818,6 @@ video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-3 {
|
||||
width: 0.75rem;
|
||||
}
|
||||
|
||||
.min-w-full {
|
||||
min-width: 100%;
|
||||
}
|
||||
@@ -938,12 +918,6 @@ video {
|
||||
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
||||
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.space-x-6 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(1.5rem * var(--tw-space-x-reverse));
|
||||
@@ -1016,10 +990,6 @@ video {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.rounded-l-lg {
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
@@ -1046,6 +1016,11 @@ video {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.border-blue-700 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(29 78 216 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-gray-200 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||
@@ -1056,31 +1031,11 @@ video {
|
||||
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-green-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(220 252 231 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-green-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(34 197 94 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-orange-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(255 237 213 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-purple-100 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(243 232 255 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-blue-700 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(29 78 216 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.bg-blue-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
||||
@@ -1111,11 +1066,6 @@ video {
|
||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(240 253 244 / var(--tw-bg-opacity));
|
||||
@@ -1126,11 +1076,6 @@ video {
|
||||
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-orange-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 237 213 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-primary-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(214 131 56 / var(--tw-bg-opacity));
|
||||
@@ -1141,11 +1086,6 @@ video {
|
||||
background-color: rgb(184 112 47 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-purple-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(243 232 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(254 242 242 / var(--tw-bg-opacity));
|
||||
@@ -1161,11 +1101,6 @@ video {
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-blue-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-opacity-50 {
|
||||
--tw-bg-opacity: 0.5;
|
||||
}
|
||||
@@ -1190,16 +1125,6 @@ video {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.px-2\.5 {
|
||||
padding-left: 0.625rem;
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
@@ -1220,16 +1145,6 @@ video {
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
|
||||
.py-0 {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.py-0\.5 {
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
@@ -1352,6 +1267,11 @@ video {
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.text-blue-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(29 78 216 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-200 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(229 231 235 / var(--tw-text-opacity));
|
||||
@@ -1387,21 +1307,11 @@ video {
|
||||
color: rgb(22 101 52 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-orange-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(154 52 18 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-primary-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(184 112 47 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-purple-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(107 33 168 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-red-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(153 27 27 / var(--tw-text-opacity));
|
||||
@@ -1412,11 +1322,6 @@ video {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-blue-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(29 78 216 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.opacity-0 {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -1478,6 +1383,11 @@ video {
|
||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-800:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
@@ -1508,16 +1418,6 @@ video {
|
||||
background-color: rgb(153 27 27 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-blue-800:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(30 64 175 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-gray-900:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
@@ -1598,6 +1498,11 @@ video {
|
||||
border-color: rgb(75 85 99 / var(--tw-divide-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-blue-500:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-gray-600:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
@@ -1608,26 +1513,6 @@ video {
|
||||
border-color: rgb(55 65 81 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-green-500:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(34 197 94 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-orange-300:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(253 186 116 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-purple-500:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(168 85 247 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-blue-500:is(.dark *) {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-blue-500:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||
@@ -1673,15 +1558,15 @@ video {
|
||||
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-blue-600:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-opacity-80:is(.dark *) {
|
||||
--tw-bg-opacity: 0.8;
|
||||
}
|
||||
|
||||
.dark\:text-blue-500:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-gray-300:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||
@@ -1702,11 +1587,6 @@ video {
|
||||
color: rgb(74 222 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-orange-300:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(253 186 116 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-primary-200:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(251 203 116 / var(--tw-text-opacity));
|
||||
@@ -1717,11 +1597,6 @@ video {
|
||||
color: rgb(244 149 65 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-purple-400:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(192 132 252 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-red-400:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(248 113 113 / var(--tw-text-opacity));
|
||||
@@ -1732,11 +1607,6 @@ video {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-blue-500:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(59 130 246 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder {
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||
@@ -1751,6 +1621,11 @@ video {
|
||||
--tw-ring-offset-color: #1f2937;
|
||||
}
|
||||
|
||||
.dark\:hover\:bg-blue-500:hover:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:bg-blue-600:hover:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
||||
@@ -1786,16 +1661,6 @@ video {
|
||||
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:bg-blue-700:hover:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:bg-blue-500:hover:is(.dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:hover\:text-primary-500:hover:is(.dark *) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(244 149 65 / var(--tw-text-opacity));
|
||||
|
||||
@@ -86,8 +86,8 @@ public class AliasTests : PlaywrightTest
|
||||
await submitButton.ClickAsync();
|
||||
await WaitForURLAsync("**/alias/**", "View alias");
|
||||
|
||||
// Check if the alias was correctly updated.
|
||||
pageContent = await Page.TextContentAsync("body");
|
||||
Assert.That(pageContent, Does.Contain("Alias updated"), "Alias update confirmation message not shown.");
|
||||
Assert.That(pageContent, Does.Contain(serviceNameAfter), "Alias not updated correctly.");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user