From ccb757c951deb7136ee0f20f008c805eb7f7d991 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Sun, 21 Dec 2025 20:25:00 +0100 Subject: [PATCH] Tweak item AddEdit secure note UI, tweak quick create (#1404) --- .../Widgets/CreateNewIdentityWidget.razor | 169 +++++++++++++++--- .../Main/Pages/Items/AddEdit.razor | 38 ++-- .../Main/Pages/Items/View.razor | 18 +- .../Widgets/CreateNewIdentityWidget.en.resx | 66 +++++-- .../Pages/Main/Items/AddEdit.en.resx | 24 +-- .../Services/QuickCreateStateService.cs | 6 + .../wwwroot/css/tailwind.css | 4 + 7 files changed, 257 insertions(+), 68 deletions(-) diff --git a/apps/server/AliasVault.Client/Main/Components/Widgets/CreateNewIdentityWidget.razor b/apps/server/AliasVault.Client/Main/Components/Widgets/CreateNewIdentityWidget.razor index 681086841..6d38b3059 100644 --- a/apps/server/AliasVault.Client/Main/Components/Widgets/CreateNewIdentityWidget.razor +++ b/apps/server/AliasVault.Client/Main/Components/Widgets/CreateNewIdentityWidget.razor @@ -1,6 +1,7 @@ @using System.ComponentModel.DataAnnotations @using Microsoft.Extensions.Localization @using AliasVault.Client.Resources +@using AliasVault.Client.Main.Models @inherits AliasVault.Client.Main.Pages.MainBase @inject IJSRuntime JSRuntime @inject ItemService ItemService @@ -19,27 +20,51 @@
-

@Localizer["CreateNewAliasTitle"]

- + @* Item Type Selector *@ +
+
+ @foreach (var itemType in ItemTypes.All) + { + + } +
+
+ +

@GetPopupTitle()

+
- +
-
- - -
+ @if (Model.ItemType == ItemTypes.Login || Model.ItemType == ItemTypes.Alias) + { +
+ + +
+ }
-
-
@@ -122,8 +147,9 @@ { IsPopupVisible = true; - // Clear the input fields + // Clear the input fields and default to Alias type Model = new(); + Model.ItemType = ItemTypes.Alias; Model.ServiceUrl = ItemService.DefaultServiceUrl; await UpdatePopupStyle(); @@ -155,9 +181,33 @@ } /// - /// Create the new identity. + /// Select an item type. /// - private async Task CreateIdentity() + private void SelectItemType(string itemType) + { + Model.ItemType = itemType; + StateHasChanged(); + } + + /// + /// Handle form submission - either create alias directly or navigate to AddEdit page. + /// + private async Task HandleFormSubmit() + { + if (Model.ItemType == ItemTypes.Alias) + { + await CreateAlias(); + } + else + { + NavigateToAddEdit(); + } + } + + /// + /// Create a new alias directly (quick create). + /// + private async Task CreateAlias() { if (IsCreating) { @@ -171,7 +221,7 @@ var item = new Item { Name = Model.ServiceName, - ItemType = "Login", + ItemType = ItemTypes.Alias, FieldValues = new List() }; @@ -209,18 +259,90 @@ } /// - /// Open the advanced mode for creating a new identity. + /// Navigate to the AddEdit page with prefilled data. /// - private void OpenAdvancedMode() + private void NavigateToAddEdit() { - // Store the form data in the state service to prefill in the advanced mode form. + // Store the form data in the state service to prefill in the AddEdit page. QuickCreateStateService.ServiceName = Model.ServiceName; QuickCreateStateService.ServiceUrl = Model.ServiceUrl; + QuickCreateStateService.ItemType = Model.ItemType; NavigationManager.NavigateTo("/items/create"); ClosePopup(); } + /// + /// Get the popup title based on the selected item type. + /// + private string GetPopupTitle() + { + return Model.ItemType switch + { + ItemTypes.Alias => Localizer["CreateNewAliasTitle"], + ItemTypes.Login => Localizer["CreateNewLoginTitle"], + ItemTypes.CreditCard => Localizer["CreateNewCreditCardTitle"], + ItemTypes.Note => Localizer["CreateNewNoteTitle"], + _ => Localizer["CreateNewAliasTitle"] + }; + } + + /// + /// Get the name placeholder based on the selected item type. + /// + private string GetNamePlaceholder() + { + return Model.ItemType switch + { + ItemTypes.Login => Localizer["NamePlaceholderLogin"], + ItemTypes.Alias => Localizer["NamePlaceholderAlias"], + ItemTypes.CreditCard => Localizer["NamePlaceholderCard"], + ItemTypes.Note => Localizer["NamePlaceholderNote"], + _ => Localizer["NamePlaceholderLogin"] + }; + } + + /// + /// Get the submit button CSS classes based on the selected item type. + /// + private string GetSubmitButtonClasses() + { + return Model.ItemType == ItemTypes.Alias + ? "bg-green-600 hover:bg-green-700" + : "bg-primary-600 hover:bg-primary-700"; + } + + /// + /// Get the display name for an item type. + /// + private string GetTypeDisplayName(string itemType) + { + return itemType switch + { + ItemTypes.Login => Localizer["TypeLogin"], + ItemTypes.Alias => Localizer["TypeAlias"], + ItemTypes.CreditCard => Localizer["TypeCard"], + ItemTypes.Note => Localizer["TypeNote"], + _ => itemType + }; + } + + /// + /// Get the icon markup for an item type. + /// + private static MarkupString GetTypeIcon(string itemType) + { + var svg = itemType switch + { + ItemTypes.Login => """""", + ItemTypes.Alias => """""", + ItemTypes.CreditCard => """""", + ItemTypes.Note => """""", + _ => """""" + }; + return new MarkupString(svg); + } + /// /// Bounding client rectangle returned from JavaScript. /// @@ -243,6 +365,11 @@ /// private sealed class CreateModel { + /// + /// The item type to create. + /// + public string ItemType { get; set; } = ItemTypes.Alias; + /// /// The service name. /// diff --git a/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor b/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor index 89e7093ee..e62c9df82 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor @@ -46,7 +46,7 @@ else @* Service/Name Section - Always shown *@
-

@GetNameSectionTitle()

+

@Localizer["ServiceSectionHeader"]

@@ -70,8 +70,8 @@ else
} - @* Notes Section - When visible *@ - @if (ShouldShowField(FieldKey.NotesContent)) + @* Notes Section - When visible (left side for non-Note types) *@ + @if (ShouldShowField(FieldKey.NotesContent) && Obj.ItemType != ItemTypes.Note) {
@@ -317,6 +317,21 @@ else
} + @* Notes Section - For Note type (main content area) *@ + @if (Obj.ItemType == ItemTypes.Note) + { +
+
+

@Localizer["NotesLabel"]

+
+
+ +
+
+
+
+ } + @* Custom Fields Section *@ @{ var customFields = Obj.GetCustomFields(); @@ -479,6 +494,10 @@ else { Obj.SetFieldValue(FieldKey.LoginUrl, QuickCreateStateService.ServiceUrl); } + if (!string.IsNullOrEmpty(QuickCreateStateService.ItemType)) + { + await HandleItemTypeChange(QuickCreateStateService.ItemType); + } // Clear the state after using it QuickCreateStateService.ClearState(); @@ -494,19 +513,6 @@ else } } - /// - /// Gets the title for the name/service section based on item type. - /// - private string GetNameSectionTitle() - { - return Obj.ItemType switch - { - ItemTypes.CreditCard => Localizer["CardNameSectionHeader"], - ItemTypes.Note => Localizer["NoteTitleSectionHeader"], - _ => Localizer["ServiceSectionHeader"] - }; - } - /// /// Checks if the current item type has login-related fields. /// diff --git a/apps/server/AliasVault.Client/Main/Pages/Items/View.razor b/apps/server/AliasVault.Client/Main/Pages/Items/View.razor index 8154491df..bf397a231 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Items/View.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Items/View.razor @@ -89,8 +89,8 @@ else } - @* Notes - if present *@ - @if (GroupedFields.TryGetValue(FieldCategory.Notes, out var notesFields) && notesFields.Count > 0) + @* Notes - if present (left column for non-Note types) *@ + @if (Item.ItemType != ItemTypes.Note && GroupedFields.TryGetValue(FieldCategory.Notes, out var notesFields) && notesFields.Count > 0) {

@Localizer["NotesSection"]

@@ -225,6 +225,20 @@ else
} + @* Notes - for Note type (main content area) *@ + @if (Item.ItemType == ItemTypes.Note && GroupedFields.TryGetValue(FieldCategory.Notes, out var noteTypeNotesFields) && noteTypeNotesFields.Count > 0) + { +
+

@Localizer["NotesSection"]

+
+ @foreach (var field in noteTypeNotesFields) + { + + } +
+
+ } + @* Custom fields *@ @if (GroupedFields.TryGetValue(FieldCategory.Custom, out var customFields) && customFields.Count > 0) { diff --git a/apps/server/AliasVault.Client/Resources/Components/Main/Widgets/CreateNewIdentityWidget.en.resx b/apps/server/AliasVault.Client/Resources/Components/Main/Widgets/CreateNewIdentityWidget.en.resx index 0bcf00597..0d6694657 100644 --- a/apps/server/AliasVault.Client/Resources/Components/Main/Widgets/CreateNewIdentityWidget.en.resx +++ b/apps/server/AliasVault.Client/Resources/Components/Main/Widgets/CreateNewIdentityWidget.en.resx @@ -59,8 +59,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + New Alias - Text for the new alias button + + New + Text for the new item button + @@ -70,25 +70,65 @@ Create New Alias Title of the create new alias popup - - Service Name - Label for service name field + + Name + Label for name field - + + Website URL + Label for website URL field + + E.g. Facebook - Placeholder text for service name field + Placeholder text for login name field - - Service URL - Label for service URL field + + E.g. Facebook + Placeholder text for alias name field + + + E.g. Mastercard + Placeholder text for card name field + + + E.g. Passport Details + Placeholder text for note name field Create Create button text - - Create via advanced mode - Link text to advanced creation mode + + Continue + Continue button text for non-alias types + + + Create New Login + Title for creating a new login item + + + Create New Card + Title for creating a new credit card item + + + Create New Note + Title for creating a new note item + + + Login + Login item type label + + + Alias + Alias item type label + + + Card + Credit card item type label (short) + + + Note + Note item type label Creating new alias... diff --git a/apps/server/AliasVault.Client/Resources/Pages/Main/Items/AddEdit.en.resx b/apps/server/AliasVault.Client/Resources/Pages/Main/Items/AddEdit.en.resx index b64d6a28e..e8ceedf09 100644 --- a/apps/server/AliasVault.Client/Resources/Pages/Main/Items/AddEdit.en.resx +++ b/apps/server/AliasVault.Client/Resources/Pages/Main/Items/AddEdit.en.resx @@ -22,11 +22,11 @@ - Add item + Add Item Title for adding a new item - Edit item + Edit Item Title for editing an existing item @@ -54,8 +54,8 @@ - Service - Header for the service information section + Item + Header for the item information section Login details @@ -76,12 +76,12 @@ - Service Name - Label for service name input + Name + Label for item name input - Service URL - Label for service URL input + Website URL + Label for website URL input Email @@ -213,14 +213,6 @@ Card Details Header for the credit card details section - - Card - Header for the card name section - - - Note - Header for the note title section - Cardholder Name Label for cardholder name input diff --git a/apps/server/AliasVault.Client/Services/QuickCreateStateService.cs b/apps/server/AliasVault.Client/Services/QuickCreateStateService.cs index a185827ee..f7dfd02f5 100644 --- a/apps/server/AliasVault.Client/Services/QuickCreateStateService.cs +++ b/apps/server/AliasVault.Client/Services/QuickCreateStateService.cs @@ -22,6 +22,11 @@ public class QuickCreateStateService /// public string? ServiceUrl { get; set; } + /// + /// Gets or sets the item type from quick create. + /// + public string? ItemType { get; set; } + /// /// Clears the stored state. /// @@ -29,5 +34,6 @@ public class QuickCreateStateService { ServiceName = null; ServiceUrl = null; + ItemType = null; } } diff --git a/apps/server/AliasVault.Client/wwwroot/css/tailwind.css b/apps/server/AliasVault.Client/wwwroot/css/tailwind.css index a4ccb4b80..609615498 100644 --- a/apps/server/AliasVault.Client/wwwroot/css/tailwind.css +++ b/apps/server/AliasVault.Client/wwwroot/css/tailwind.css @@ -1718,6 +1718,10 @@ video { border-color: rgb(254 240 138 / var(--tw-border-opacity)); } +.border-transparent { + border-color: transparent; +} + .bg-amber-100 { --tw-bg-opacity: 1; background-color: rgb(254 243 199 / var(--tw-bg-opacity));