diff --git a/apps/server/AliasVault.Client/Main/Models/CustomFieldEdit.cs b/apps/server/AliasVault.Client/Main/Models/CustomFieldEdit.cs deleted file mode 100644 index 9a8e71c93..000000000 --- a/apps/server/AliasVault.Client/Main/Models/CustomFieldEdit.cs +++ /dev/null @@ -1,51 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) aliasvault. All rights reserved. -// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information. -// -//----------------------------------------------------------------------- - -namespace AliasVault.Client.Main.Models; - -using System; - -/// -/// Model for custom field editing. -/// -public sealed class CustomFieldEdit -{ - /// - /// Gets or sets the field value ID (for existing fields). - /// - public Guid Id { get; set; } - - /// - /// Gets or sets the field definition ID. - /// - public Guid FieldDefinitionId { get; set; } - - /// - /// Gets or sets the temporary ID for new custom fields (format: custom_{uuid}). - /// - public string? TempId { get; set; } - - /// - /// Gets or sets the field label. - /// - public string Label { get; set; } = string.Empty; - - /// - /// Gets or sets the field type. - /// - public string FieldType { get; set; } = "Text"; - - /// - /// Gets or sets the field value. - /// - public string Value { get; set; } = string.Empty; - - /// - /// Gets or sets a value indicating whether the field is hidden/masked. - /// - public bool IsHidden { get; set; } -} diff --git a/apps/server/AliasVault.Client/Main/Models/ItemEdit.cs b/apps/server/AliasVault.Client/Main/Models/ItemEdit.cs index 618908765..58b81c020 100644 --- a/apps/server/AliasVault.Client/Main/Models/ItemEdit.cs +++ b/apps/server/AliasVault.Client/Main/Models/ItemEdit.cs @@ -10,16 +10,15 @@ namespace AliasVault.Client.Main.Models; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Globalization; using System.Linq; using AliasClientDb; using AliasClientDb.Models; -using AliasVault.Client.Main.Models.FormValidation; using AliasVault.Client.Resources; using AliasVault.Client.Services; /// /// Item edit model for add/edit forms. +/// Uses a dynamic fields-based approach for flexibility when adding new system fields. /// public sealed class ItemEdit { @@ -40,11 +39,6 @@ public sealed class ItemEdit [Display(Name = "Service Name")] public string ServiceName { get; set; } = string.Empty; - /// - /// Gets or sets the URL of the service. - /// - public string? ServiceUrl { get; set; } - /// /// Gets or sets the logo ID. /// @@ -60,77 +54,6 @@ public sealed class ItemEdit /// public Guid? FolderId { get; set; } - /// - /// Gets or sets the username field. - /// - public string Username { get; set; } = string.Empty; - - /// - /// Gets or sets the password field. - /// - public string Password { get; set; } = string.Empty; - - /// - /// Gets or sets the email field. - /// - public string Email { get; set; } = string.Empty; - - /// - /// Gets or sets the notes field. - /// - public string Notes { get; set; } = string.Empty; - - /// - /// Gets or sets the Alias first name. - /// - public string AliasFirstName { get; set; } = string.Empty; - - /// - /// Gets or sets the Alias last name. - /// - public string AliasLastName { get; set; } = string.Empty; - - /// - /// Gets or sets the Alias gender. - /// - public string AliasGender { get; set; } = string.Empty; - - /// - /// Gets or sets the Alias BirthDate. Can be empty string or a date in yyyy-MM-dd format. - /// - [StringDateFormat("yyyy-MM-dd", AllowEmpty = true)] - public string AliasBirthDate { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card number. - /// - public string CardNumber { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card cardholder name. - /// - public string CardCardholderName { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card expiry month. - /// - public string CardExpiryMonth { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card expiry year. - /// - public string CardExpiryYear { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card CVV. - /// - public string CardCvv { get; set; } = string.Empty; - - /// - /// Gets or sets the credit card PIN. - /// - public string CardPin { get; set; } = string.Empty; - /// /// Gets or sets the create date. /// @@ -141,6 +64,11 @@ public sealed class ItemEdit /// public DateTime LastUpdate { get; set; } + /// + /// Gets or sets the dynamic fields list (both system and custom fields). + /// + public List Fields { get; set; } = []; + /// /// Gets or sets the Attachment list. /// @@ -156,11 +84,6 @@ public sealed class ItemEdit /// public List Passkeys { get; set; } = []; - /// - /// Gets or sets the custom fields. - /// - public List CustomFields { get; set; } = []; - /// /// Creates an ItemEdit instance from an Item entity. /// @@ -168,31 +91,14 @@ public sealed class ItemEdit /// A new ItemEdit instance. public static ItemEdit FromEntity(Item item) { - var birthDate = ItemService.GetFieldValue(item, FieldKey.AliasBirthdate); - var edit = new ItemEdit { Id = item.Id, ItemType = item.ItemType, ServiceName = item.Name ?? string.Empty, - ServiceUrl = ItemService.GetFieldValue(item, FieldKey.LoginUrl), LogoId = item.LogoId, ServiceLogo = item.Logo?.FileData, FolderId = item.FolderId, - Username = ItemService.GetFieldValue(item, FieldKey.LoginUsername) ?? string.Empty, - Password = ItemService.GetFieldValue(item, FieldKey.LoginPassword) ?? string.Empty, - Email = ItemService.GetFieldValue(item, FieldKey.LoginEmail) ?? string.Empty, - Notes = ItemService.GetFieldValue(item, FieldKey.NotesContent) ?? string.Empty, - AliasFirstName = ItemService.GetFieldValue(item, FieldKey.AliasFirstName) ?? string.Empty, - AliasLastName = ItemService.GetFieldValue(item, FieldKey.AliasLastName) ?? string.Empty, - AliasGender = ItemService.GetFieldValue(item, FieldKey.AliasGender) ?? string.Empty, - AliasBirthDate = birthDate ?? string.Empty, - CardNumber = ItemService.GetFieldValue(item, FieldKey.CardNumber) ?? string.Empty, - CardCardholderName = ItemService.GetFieldValue(item, FieldKey.CardCardholderName) ?? string.Empty, - CardExpiryMonth = ItemService.GetFieldValue(item, FieldKey.CardExpiryMonth) ?? string.Empty, - CardExpiryYear = ItemService.GetFieldValue(item, FieldKey.CardExpiryYear) ?? string.Empty, - CardCvv = ItemService.GetFieldValue(item, FieldKey.CardCvv) ?? string.Empty, - CardPin = ItemService.GetFieldValue(item, FieldKey.CardPin) ?? string.Empty, Attachments = item.Attachments.Where(a => !a.IsDeleted).ToList(), TotpCodes = item.TotpCodes.Where(t => !t.IsDeleted).ToList(), Passkeys = item.Passkeys.Where(p => !p.IsDeleted).ToList(), @@ -200,17 +106,34 @@ public sealed class ItemEdit LastUpdate = item.UpdatedAt, }; - // Extract custom fields (non-system fields that have FieldDefinitionId set) - foreach (var fv in item.FieldValues.Where(f => !f.IsDeleted && f.FieldDefinitionId != null)) + // Convert all field values to SystemFieldEdit + foreach (var fv in item.FieldValues.Where(f => !f.IsDeleted)) { - edit.CustomFields.Add(new CustomFieldEdit + var isCustomField = fv.FieldDefinitionId != null && string.IsNullOrEmpty(fv.FieldKey); + var systemField = !string.IsNullOrEmpty(fv.FieldKey) ? SystemFieldRegistry.GetSystemField(fv.FieldKey) : null; + + edit.Fields.Add(new SystemFieldEdit { - Id = fv.Id, - FieldDefinitionId = fv.FieldDefinitionId!.Value, - Label = fv.FieldDefinition?.Label ?? "Custom Field", - FieldType = fv.FieldDefinition?.FieldType ?? "Text", + FieldKey = fv.FieldKey ?? fv.FieldDefinitionId?.ToString() ?? string.Empty, + FieldValueId = fv.Id, + FieldDefinitionId = fv.FieldDefinitionId, + Label = isCustomField + ? fv.FieldDefinition?.Label ?? "Custom Field" + : fv.FieldKey ?? string.Empty, + FieldType = isCustomField + ? fv.FieldDefinition?.FieldType ?? "Text" + : systemField?.FieldType ?? "Text", Value = fv.Value ?? string.Empty, - IsHidden = fv.FieldDefinition?.IsHidden ?? false, + IsCustomField = isCustomField, + IsHidden = isCustomField + ? fv.FieldDefinition?.IsHidden ?? false + : systemField?.IsHidden ?? false, + EnableHistory = isCustomField + ? fv.FieldDefinition?.EnableHistory ?? false + : systemField?.EnableHistory ?? false, + DisplayOrder = systemField?.DefaultDisplayOrder ?? fv.Weight, + Category = GetCategoryFromFieldKey(fv.FieldKey), + IsMultiValue = systemField?.IsMultiValue ?? false, }); } @@ -234,152 +157,77 @@ public sealed class ItemEdit TotpCodes = TotpCodes, }; - // Add login fields - if (!string.IsNullOrEmpty(ServiceUrl)) + // Convert all fields to FieldValue entities + foreach (var field in Fields.Where(f => !string.IsNullOrEmpty(f.Value))) { - ItemService.SetFieldValue(item, FieldKey.LoginUrl, ServiceUrl); - } - - if (!string.IsNullOrEmpty(Username)) - { - ItemService.SetFieldValue(item, FieldKey.LoginUsername, Username); - } - - if (!string.IsNullOrEmpty(Password)) - { - ItemService.SetFieldValue(item, FieldKey.LoginPassword, Password); - } - - if (!string.IsNullOrEmpty(Email)) - { - ItemService.SetFieldValue(item, FieldKey.LoginEmail, Email); - } - - if (!string.IsNullOrEmpty(Notes)) - { - ItemService.SetFieldValue(item, FieldKey.NotesContent, Notes); - } - - // Add alias fields - if (!string.IsNullOrEmpty(AliasFirstName)) - { - ItemService.SetFieldValue(item, FieldKey.AliasFirstName, AliasFirstName); - } - - if (!string.IsNullOrEmpty(AliasLastName)) - { - ItemService.SetFieldValue(item, FieldKey.AliasLastName, AliasLastName); - } - - if (!string.IsNullOrEmpty(AliasGender)) - { - ItemService.SetFieldValue(item, FieldKey.AliasGender, AliasGender); - } - - if (!string.IsNullOrEmpty(AliasBirthDate)) - { - ItemService.SetFieldValue(item, FieldKey.AliasBirthdate, AliasBirthDate); - } - - // Add card fields - if (!string.IsNullOrEmpty(CardNumber)) - { - ItemService.SetFieldValue(item, FieldKey.CardNumber, CardNumber); - } - - if (!string.IsNullOrEmpty(CardCardholderName)) - { - ItemService.SetFieldValue(item, FieldKey.CardCardholderName, CardCardholderName); - } - - if (!string.IsNullOrEmpty(CardExpiryMonth)) - { - ItemService.SetFieldValue(item, FieldKey.CardExpiryMonth, CardExpiryMonth); - } - - if (!string.IsNullOrEmpty(CardExpiryYear)) - { - ItemService.SetFieldValue(item, FieldKey.CardExpiryYear, CardExpiryYear); - } - - if (!string.IsNullOrEmpty(CardCvv)) - { - ItemService.SetFieldValue(item, FieldKey.CardCvv, CardCvv); - } - - if (!string.IsNullOrEmpty(CardPin)) - { - ItemService.SetFieldValue(item, FieldKey.CardPin, CardPin); - } - - // Add custom fields - foreach (var customField in CustomFields.Where(cf => !string.IsNullOrEmpty(cf.Value))) - { - // For new custom fields (TempId set, FieldDefinitionId is empty), create a new FieldDefinition. - // The FieldDefinition.Id is a plain GUID - no prefix needed. - // Custom fields are identified by having FieldDefinitionId set (not FieldKey). - if (customField.FieldDefinitionId == Guid.Empty && !string.IsNullOrEmpty(customField.TempId)) + if (field.IsCustomField) { + // Custom field handling var now = DateTime.UtcNow; - // TempId is a plain GUID string - var fieldDefinitionId = Guid.TryParse(customField.TempId, out var parsedGuid) - ? parsedGuid - : Guid.NewGuid(); + if (field.FieldDefinitionId == null || field.FieldDefinitionId == Guid.Empty) + { + // New custom field - create FieldDefinition + var fieldDefinitionId = !string.IsNullOrEmpty(field.TempId) && Guid.TryParse(field.TempId, out var parsedGuid) + ? parsedGuid + : Guid.NewGuid(); - var fieldDefinition = new FieldDefinition - { - Id = fieldDefinitionId, - FieldType = customField.FieldType, - Label = customField.Label, - IsHidden = customField.IsHidden, - IsMultiValue = false, - EnableHistory = false, - Weight = 0, - CreatedAt = now, - UpdatedAt = now, - }; + var fieldDefinition = new FieldDefinition + { + Id = fieldDefinitionId, + FieldType = field.FieldType, + Label = field.Label, + IsHidden = field.IsHidden, + IsMultiValue = false, + EnableHistory = false, + Weight = 0, + CreatedAt = now, + UpdatedAt = now, + }; - item.FieldValues.Add(new FieldValue + item.FieldValues.Add(new FieldValue + { + Id = Guid.NewGuid(), + ItemId = item.Id, + FieldDefinitionId = fieldDefinitionId, + FieldDefinition = fieldDefinition, + FieldKey = null, + Value = field.Value, + Weight = 0, + }); + } + else { - Id = Guid.NewGuid(), - ItemId = item.Id, - FieldDefinitionId = fieldDefinitionId, - FieldDefinition = fieldDefinition, - FieldKey = null, - Value = customField.Value, - Weight = 0, - }); - } - else - { - // Existing custom field - update value and include FieldDefinition with updated label - var fieldValue = new FieldValue - { - Id = customField.Id != Guid.Empty ? customField.Id : Guid.NewGuid(), - ItemId = item.Id, - FieldDefinitionId = customField.FieldDefinitionId, - FieldKey = null, - Value = customField.Value, - Weight = 0, - }; + // Existing custom field - update value and include FieldDefinition + var fieldValue = new FieldValue + { + Id = field.FieldValueId != Guid.Empty ? field.FieldValueId : Guid.NewGuid(), + ItemId = item.Id, + FieldDefinitionId = field.FieldDefinitionId, + FieldKey = null, + Value = field.Value, + Weight = 0, + }; - // Include FieldDefinition with potentially updated label for update logic - if (customField.FieldDefinitionId != Guid.Empty) - { + // Include FieldDefinition with potentially updated label fieldValue.FieldDefinition = new FieldDefinition { - Id = customField.FieldDefinitionId, - Label = customField.Label, - FieldType = customField.FieldType, - IsHidden = customField.IsHidden, + Id = field.FieldDefinitionId.Value, + Label = field.Label, + FieldType = field.FieldType, + IsHidden = field.IsHidden, IsMultiValue = false, EnableHistory = false, Weight = 0, }; - } - item.FieldValues.Add(fieldValue); + item.FieldValues.Add(fieldValue); + } + } + else + { + // System field + ItemService.SetFieldValue(item, field.FieldKey, field.Value); } } @@ -387,87 +235,86 @@ public sealed class ItemEdit } /// - /// Gets the value of a system field by its field key. + /// Gets the value of a field by its field key. /// /// The field key. /// The field value or empty string. public string GetFieldValue(string fieldKey) { - return fieldKey switch - { - FieldKey.LoginUrl => ServiceUrl ?? string.Empty, - FieldKey.LoginUsername => Username, - FieldKey.LoginPassword => Password, - FieldKey.LoginEmail => Email, - FieldKey.NotesContent => Notes, - FieldKey.AliasFirstName => AliasFirstName, - FieldKey.AliasLastName => AliasLastName, - FieldKey.AliasGender => AliasGender, - FieldKey.AliasBirthdate => AliasBirthDate, - FieldKey.CardNumber => CardNumber, - FieldKey.CardCardholderName => CardCardholderName, - FieldKey.CardExpiryMonth => CardExpiryMonth, - FieldKey.CardExpiryYear => CardExpiryYear, - FieldKey.CardCvv => CardCvv, - FieldKey.CardPin => CardPin, - _ => string.Empty, - }; + return Fields.FirstOrDefault(f => f.FieldKey == fieldKey)?.Value ?? string.Empty; } /// - /// Sets the value of a system field by its field key. + /// Gets a field by its field key. + /// If the field doesn't exist, creates it based on the system field definition. + /// + /// The field key. + /// The field or null if not a valid system field. + public SystemFieldEdit? GetField(string fieldKey) + { + var field = Fields.FirstOrDefault(f => f.FieldKey == fieldKey); + if (field != null) + { + return field; + } + + // Field doesn't exist - create it if it's a valid system field + var systemField = SystemFieldRegistry.GetSystemField(fieldKey); + if (systemField == null) + { + return null; + } + + field = new SystemFieldEdit + { + FieldKey = fieldKey, + Label = fieldKey, + FieldType = systemField.FieldType, + Value = string.Empty, + IsCustomField = false, + IsHidden = systemField.IsHidden, + EnableHistory = systemField.EnableHistory, + DisplayOrder = systemField.DefaultDisplayOrder, + Category = systemField.Category, + IsMultiValue = systemField.IsMultiValue, + }; + Fields.Add(field); + return field; + } + + /// + /// Sets the value of a field by its field key. + /// If the field doesn't exist, it will be added. /// /// The field key. /// The value to set. public void SetFieldValue(string fieldKey, string value) { - switch (fieldKey) + var field = Fields.FirstOrDefault(f => f.FieldKey == fieldKey); + if (field != null) { - case FieldKey.LoginUrl: - ServiceUrl = value; - break; - case FieldKey.LoginUsername: - Username = value; - break; - case FieldKey.LoginPassword: - Password = value; - break; - case FieldKey.LoginEmail: - Email = value; - break; - case FieldKey.NotesContent: - Notes = value; - break; - case FieldKey.AliasFirstName: - AliasFirstName = value; - break; - case FieldKey.AliasLastName: - AliasLastName = value; - break; - case FieldKey.AliasGender: - AliasGender = value; - break; - case FieldKey.AliasBirthdate: - AliasBirthDate = value; - break; - case FieldKey.CardNumber: - CardNumber = value; - break; - case FieldKey.CardCardholderName: - CardCardholderName = value; - break; - case FieldKey.CardExpiryMonth: - CardExpiryMonth = value; - break; - case FieldKey.CardExpiryYear: - CardExpiryYear = value; - break; - case FieldKey.CardCvv: - CardCvv = value; - break; - case FieldKey.CardPin: - CardPin = value; - break; + field.Value = value; + } + else + { + // Add new field based on system field definition + var systemField = SystemFieldRegistry.GetSystemField(fieldKey); + if (systemField != null) + { + Fields.Add(new SystemFieldEdit + { + FieldKey = fieldKey, + Label = fieldKey, + FieldType = systemField.FieldType, + Value = value, + IsCustomField = false, + IsHidden = systemField.IsHidden, + EnableHistory = systemField.EnableHistory, + DisplayOrder = systemField.DefaultDisplayOrder, + Category = systemField.Category, + IsMultiValue = systemField.IsMultiValue, + }); + } } } @@ -480,4 +327,167 @@ public sealed class ItemEdit { return !string.IsNullOrEmpty(GetFieldValue(fieldKey)); } + + /// + /// Gets all custom fields. + /// + /// List of custom fields. + public List GetCustomFields() + { + return Fields.Where(f => f.IsCustomField).ToList(); + } + + /// + /// Gets all system fields. + /// + /// List of system fields. + public List GetSystemFields() + { + return Fields.Where(f => !f.IsCustomField).ToList(); + } + + /// + /// Adds a new custom field. + /// + /// The field label. + /// The field type. + public void AddCustomField(string label, string fieldType) + { + var tempId = Guid.NewGuid().ToString(); + Fields.Add(new SystemFieldEdit + { + FieldKey = tempId, + TempId = tempId, + Label = label, + FieldType = fieldType, + Value = string.Empty, + IsCustomField = true, + IsHidden = fieldType == "Hidden" || fieldType == "Password", + EnableHistory = false, + DisplayOrder = Fields.Count, + Category = FieldCategory.Custom, + IsMultiValue = false, + }); + } + + /// + /// Removes a custom field by its field key (TempId or FieldDefinitionId). + /// + /// The field key to remove. + public void RemoveCustomField(string fieldKey) + { + var field = Fields.FirstOrDefault(f => f.FieldKey == fieldKey && f.IsCustomField); + if (field != null) + { + Fields.Remove(field); + } + } + + /// + /// Updates the label of a custom field. + /// + /// The field key. + /// The new label. + public void UpdateCustomFieldLabel(string fieldKey, string newLabel) + { + var field = Fields.FirstOrDefault(f => f.FieldKey == fieldKey && f.IsCustomField); + if (field != null) + { + field.Label = newLabel; + } + } + + /// + /// Removes a field by its field key and clears its value. + /// + /// The field key to remove. + public void RemoveField(string fieldKey) + { + var field = Fields.FirstOrDefault(f => f.FieldKey == fieldKey); + if (field != null) + { + if (field.IsCustomField) + { + Fields.Remove(field); + } + else + { + // For system fields, just clear the value (they can be re-added) + field.Value = string.Empty; + } + } + } + + /// + /// Gets fields by category. + /// + /// The category to filter by. + /// List of fields in the specified category. + public List GetFieldsByCategory(FieldCategory category) + { + return Fields + .Where(f => f.Category == category && !string.IsNullOrEmpty(f.Value)) + .OrderBy(f => f.DisplayOrder) + .ToList(); + } + + /// + /// Clears all field values for a specific item type that don't apply to the new type. + /// + /// The new item type. + public void ClearFieldsNotApplicableToType(string newItemType) + { + foreach (var field in Fields.Where(f => !f.IsCustomField).ToList()) + { + var systemField = SystemFieldRegistry.GetSystemField(field.FieldKey); + if (systemField != null && !SystemFieldRegistry.FieldAppliesToType(systemField, newItemType)) + { + field.Value = string.Empty; + } + } + } + + /// + /// Gets the field category from a field key based on its prefix. + /// + private static FieldCategory GetCategoryFromFieldKey(string? fieldKey) + { + if (string.IsNullOrEmpty(fieldKey)) + { + return FieldCategory.Custom; + } + + if (fieldKey.StartsWith("login.")) + { + // URL is in Primary category + if (fieldKey == FieldKey.LoginUrl) + { + return FieldCategory.Primary; + } + + return FieldCategory.Login; + } + + if (fieldKey.StartsWith("alias.")) + { + return FieldCategory.Alias; + } + + if (fieldKey.StartsWith("card.")) + { + return FieldCategory.Card; + } + + if (fieldKey.StartsWith("notes.")) + { + return FieldCategory.Notes; + } + + if (fieldKey.StartsWith("metadata.")) + { + return FieldCategory.Metadata; + } + + return FieldCategory.Custom; + } } diff --git a/apps/server/AliasVault.Client/Main/Models/SystemFieldEdit.cs b/apps/server/AliasVault.Client/Main/Models/SystemFieldEdit.cs new file mode 100644 index 000000000..1c76c2e00 --- /dev/null +++ b/apps/server/AliasVault.Client/Main/Models/SystemFieldEdit.cs @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) aliasvault. All rights reserved. +// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- + +namespace AliasVault.Client.Main.Models; + +using System; +using AliasClientDb.Models; + +/// +/// Represents a field for editing in the UI. +/// Unifies both system fields (from SystemFieldRegistry) and custom fields for the edit form. +/// +public sealed class SystemFieldEdit +{ + /// + /// Gets or sets the field key. + /// For system fields: the system field key (e.g., 'login.username'). + /// For custom fields: the FieldDefinitionId as a string. + /// + public string FieldKey { get; set; } = string.Empty; + + /// + /// Gets or sets the field value ID (for existing fields only). + /// + public Guid FieldValueId { get; set; } + + /// + /// Gets or sets the field definition ID (for custom fields only). + /// + public Guid? FieldDefinitionId { get; set; } + + /// + /// Gets or sets the temporary ID for new custom fields (a GUID string). + /// + public string? TempId { get; set; } + + /// + /// Gets or sets the label for this field. + /// For system fields, this is the field key (UI layer translates via fieldLabels.*). + /// For custom fields, this is the user-defined label. + /// + public string Label { get; set; } = string.Empty; + + /// + /// Gets or sets the field type for rendering (Text, Password, Email, URL, Date, etc.). + /// + public string FieldType { get; set; } = "Text"; + + /// + /// Gets or sets the field value. + /// + public string Value { get; set; } = string.Empty; + + /// + /// Gets or sets a value indicating whether this is a custom field. + /// + public bool IsCustomField { get; set; } + + /// + /// Gets or sets a value indicating whether the field is hidden/masked. + /// + public bool IsHidden { get; set; } + + /// + /// Gets or sets a value indicating whether history is enabled for this field. + /// + public bool EnableHistory { get; set; } + + /// + /// Gets or sets the display order. + /// + public int DisplayOrder { get; set; } + + /// + /// Gets or sets the field category. + /// + public FieldCategory Category { get; set; } + + /// + /// Gets or sets a value indicating whether the field supports multiple values. + /// + public bool IsMultiValue { get; set; } +} diff --git a/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor b/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor index 18df37104..89e7093ee 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Items/AddEdit.razor @@ -56,7 +56,7 @@ else @if (ShouldShowField(FieldKey.LoginUrl)) {
- +
} @@ -76,7 +76,7 @@ else
- +
@@ -109,7 +109,7 @@ else var passkey = Obj.Passkeys.First(); @* With passkey: Username, Passkey, Email, Password *@
- +
@if (!PasskeyMarkedForDeletion) { @@ -182,10 +182,10 @@ else }
- +
- +
} else @@ -194,7 +194,7 @@ else @if (ShouldShowField(FieldKey.LoginEmail)) {
- + @if (CanRemoveField(FieldKey.LoginEmail)) {
- +
} @@ -259,17 +259,16 @@ else
- +
- +
- +
- - +
@@ -284,24 +283,24 @@ else

@Localizer["CardDetailsSectionHeader"]

- +
- +
- +
- +
- +
@if (ShouldShowField(FieldKey.CardPin)) {
- + @if (CanRemoveField(FieldKey.CardPin)) {