From c0865f655078abf11bb547e800f83c7f3d8216dd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 11:41:55 +0000
Subject: [PATCH 1/5] Initial plan
From e1b8bc1c625464b61d15101830aa6b16ff93b6e0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 11:46:08 +0000
Subject: [PATCH 2/5] Initial assessment: Add tags editing capability to Azure
Key Vault Explorer
Co-authored-by: cricketthomas <15821271+cricketthomas@users.noreply.github.com>
---
Desktop/Desktop.csproj | 4 ++--
KeyVaultExplorer/KeyVaultExplorer.csproj | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj
index b4e4180..a0b1345 100644
--- a/Desktop/Desktop.csproj
+++ b/Desktop/Desktop.csproj
@@ -3,9 +3,9 @@
WinExe
- net9.0
+ net8.0
- $(TargetFrameworks);net9.0-windows10.0.19041.0
+ $(TargetFrameworks);net8.0-windows10.0.19041.0
10.0.19041.41
enable
diff --git a/KeyVaultExplorer/KeyVaultExplorer.csproj b/KeyVaultExplorer/KeyVaultExplorer.csproj
index 263decf..3ed8295 100644
--- a/KeyVaultExplorer/KeyVaultExplorer.csproj
+++ b/KeyVaultExplorer/KeyVaultExplorer.csproj
@@ -1,7 +1,7 @@
- net9.0
- $(TargetFrameworks);net9.0-windows10.0.19041.0
+ net8.0
+ $(TargetFrameworks);net8.0-windows10.0.19041.0
10.0.19041.41
From 37eafe4c0e8746f845bbff6f2219e32845fd564e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 11:51:28 +0000
Subject: [PATCH 3/5] Add basic tags editing functionality for secrets with
TagsEditor control
Co-authored-by: cricketthomas <15821271+cricketthomas@users.noreply.github.com>
---
KeyVaultExplorer/Services/VaultService.cs | 8 ++
.../CreateNewSecretVersionViewModel.cs | 23 +++++
.../Views/CustomControls/TagsEditor.axaml | 61 ++++++++++++
.../Views/CustomControls/TagsEditor.axaml.cs | 98 +++++++++++++++++++
.../CreateNewSecretVersion.axaml | 7 ++
.../CreateNewSecretVersion.axaml.cs | 20 ++++
6 files changed, 217 insertions(+)
create mode 100644 KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml
create mode 100644 KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml.cs
diff --git a/KeyVaultExplorer/Services/VaultService.cs b/KeyVaultExplorer/Services/VaultService.cs
index af146bc..0f6857f 100644
--- a/KeyVaultExplorer/Services/VaultService.cs
+++ b/KeyVaultExplorer/Services/VaultService.cs
@@ -357,4 +357,12 @@ public async Task UpdateSecret(SecretProperties properties, Ur
var client = new SecretClient(KeyVaultUri, token);
return await client.UpdateSecretPropertiesAsync(properties);
}
+
+ public async Task UpdateCertificate(CertificateProperties properties, Uri KeyVaultUri)
+ {
+ var token = new CustomTokenCredential(await _authService.GetAzureKeyVaultTokenSilent());
+ var client = new CertificateClient(KeyVaultUri, token);
+ var response = await client.UpdateCertificatePropertiesAsync(properties);
+ return response.Value.Properties;
+ }
}
\ No newline at end of file
diff --git a/KeyVaultExplorer/ViewModels/CreateNewSecretVersionViewModel.cs b/KeyVaultExplorer/ViewModels/CreateNewSecretVersionViewModel.cs
index e6bdd7a..194314d 100644
--- a/KeyVaultExplorer/ViewModels/CreateNewSecretVersionViewModel.cs
+++ b/KeyVaultExplorer/ViewModels/CreateNewSecretVersionViewModel.cs
@@ -4,6 +4,7 @@
using KeyVaultExplorer.Services;
using KeyVaultExplorer.Validations;
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
@@ -64,6 +65,9 @@ public CreateNewSecretVersionViewModel()
ValidateAllProperties();
}
+ // Delegate to get updated tags from the UI
+ public Func>? GetUpdatedTags { get; set; }
+
[ObservableProperty]
public bool hasActivationDateChecked;
@@ -86,6 +90,9 @@ public async Task EditDetails()
else
KeyVaultSecretModel.ExpiresOn = null;
+ // Update tags from the TagsEditor if available
+ UpdateTagsFromEditor();
+
var updatedProps = await _vaultService.UpdateSecret(KeyVaultSecretModel, KeyVaultSecretModel.VaultUri);
KeyVaultSecretModel = updatedProps;
}
@@ -102,6 +109,9 @@ private async Task NewVersion()
newSecret.Properties.ContentType = KeyVaultSecretModel.ContentType;
+ // Update tags from the TagsEditor before creating new version
+ UpdateTagsFromEditor();
+
foreach (var tag in KeyVaultSecretModel.Tags)
newSecret.Properties.Tags.Add(tag.Key, tag.Value);
@@ -137,6 +147,19 @@ partial void OnHasExpirationDateCheckedChanged(bool oldValue, bool newValue)
}
}
+ private void UpdateTagsFromEditor()
+ {
+ if (GetUpdatedTags != null)
+ {
+ var updatedTags = GetUpdatedTags();
+ KeyVaultSecretModel.Tags.Clear();
+ foreach (var tag in updatedTags)
+ {
+ KeyVaultSecretModel.Tags[tag.Key] = tag.Value;
+ }
+ }
+ }
+
//public async Task> GetAvailableSubscriptions()
//{
// var subscriptions = new List();
diff --git a/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml b/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml
new file mode 100644
index 0000000..0a1e1d9
--- /dev/null
+++ b/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml.cs b/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml.cs
new file mode 100644
index 0000000..8301f7c
--- /dev/null
+++ b/KeyVaultExplorer/Views/CustomControls/TagsEditor.axaml.cs
@@ -0,0 +1,98 @@
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+
+namespace KeyVaultExplorer.Views.CustomControls;
+
+public partial class TagsEditor : UserControl
+{
+ private ObservableCollection _tags = new();
+
+ public TagsEditor()
+ {
+ InitializeComponent();
+ DataContext = this;
+ }
+
+ public ObservableCollection Tags
+ {
+ get => _tags;
+ set => _tags = value;
+ }
+
+ public IDictionary TagsDictionary
+ {
+ get
+ {
+ var dict = new Dictionary();
+ foreach (var tag in Tags)
+ {
+ if (!string.IsNullOrWhiteSpace(tag.Key) && !string.IsNullOrWhiteSpace(tag.Value))
+ {
+ dict[tag.Key] = tag.Value;
+ }
+ }
+ return dict;
+ }
+ set
+ {
+ Tags.Clear();
+ if (value != null)
+ {
+ foreach (var kvp in value)
+ {
+ Tags.Add(new TagItem { Key = kvp.Key, Value = kvp.Value });
+ }
+ }
+ }
+ }
+
+ private void AddTag_Click(object? sender, RoutedEventArgs e)
+ {
+ Tags.Add(new TagItem { Key = "", Value = "" });
+ }
+
+ private void RemoveTag_Click(object? sender, RoutedEventArgs e)
+ {
+ if (sender is Button button && button.Tag is TagItem tagItem)
+ {
+ Tags.Remove(tagItem);
+ }
+ }
+}
+
+public class TagItem : INotifyPropertyChanged
+{
+ private string _key = "";
+ private string _value = "";
+
+ public string Key
+ {
+ get => _key;
+ set
+ {
+ _key = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Value
+ {
+ get => _value;
+ set
+ {
+ _value = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+}
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/CreateNewSecretVersion.axaml b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/CreateNewSecretVersion.axaml
index 5414079..45c9de4 100644
--- a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/CreateNewSecretVersion.axaml
+++ b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/CreateNewSecretVersion.axaml
@@ -8,6 +8,7 @@
xmlns:models="clr-namespace:KeyVaultExplorer.Models;assembly=KeyVaultExplorer"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:vm="clr-namespace:KeyVaultExplorer.ViewModels"
+ xmlns:controls="using:KeyVaultExplorer.Views.CustomControls"
d:DesignHeight="450"
d:DesignWidth="600"
x:DataType="vm:CreateNewSecretVersionViewModel"
@@ -127,6 +128,12 @@
+
+
+
+
+
+
TagsEditor.TagsDictionary;
+
+ // Subscribe to ViewModel property changes to sync tags
+ vm.PropertyChanged += OnViewModelPropertyChanged;
+ }
+
+ private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(CreateNewSecretVersionViewModel.KeyVaultSecretModel) &&
+ DataContext is CreateNewSecretVersionViewModel vm)
+ {
+ // Update TagsEditor when KeyVaultSecretModel changes
+ if (vm.KeyVaultSecretModel?.Tags != null)
+ {
+ TagsEditor.TagsDictionary = vm.KeyVaultSecretModel.Tags;
+ }
+ }
}
//private void Subscription_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e)
From 92b1ffac37b3b18d434bba959cf224c71a2a5f68 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 11:57:21 +0000
Subject: [PATCH 4/5] Add comprehensive tags editing for all Key Vault item
types (secrets, keys, certificates)
Co-authored-by: cricketthomas <15821271+cricketthomas@users.noreply.github.com>
---
.../EditCertificateVersionViewModel.cs | 96 ++++++++++++++++
.../ViewModels/EditKeyVersionViewModel.cs | 107 ++++++++++++++++++
.../ViewModels/PropertiesPageViewModel.cs | 66 +++++++++++
.../EditCertificateVersion.axaml | 61 ++++++++++
.../EditCertificateVersion.axaml.cs | 47 ++++++++
.../PropertiesDialogs/EditKeyVersion.axaml | 85 ++++++++++++++
.../PropertiesDialogs/EditKeyVersion.axaml.cs | 47 ++++++++
.../Views/Pages/PropertiesPage.axaml | 1 -
8 files changed, 509 insertions(+), 1 deletion(-)
create mode 100644 KeyVaultExplorer/ViewModels/EditCertificateVersionViewModel.cs
create mode 100644 KeyVaultExplorer/ViewModels/EditKeyVersionViewModel.cs
create mode 100644 KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml
create mode 100644 KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml.cs
create mode 100644 KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml
create mode 100644 KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml.cs
diff --git a/KeyVaultExplorer/ViewModels/EditCertificateVersionViewModel.cs b/KeyVaultExplorer/ViewModels/EditCertificateVersionViewModel.cs
new file mode 100644
index 0000000..4871cd7
--- /dev/null
+++ b/KeyVaultExplorer/ViewModels/EditCertificateVersionViewModel.cs
@@ -0,0 +1,96 @@
+using Azure.Security.KeyVault.Certificates;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using KeyVaultExplorer.Services;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace KeyVaultExplorer.ViewModels;
+
+public partial class EditCertificateVersionViewModel : ViewModelBase
+{
+ private readonly AuthService _authService;
+ private readonly VaultService _vaultService;
+ private readonly NotificationViewModel _notificationViewModel;
+
+ [ObservableProperty]
+ private TimeSpan? expiresOnTimespan;
+
+ [ObservableProperty]
+ private bool isBusy = false;
+
+ [ObservableProperty]
+ private CertificateProperties keyVaultCertificateModel = new CertificateProperties("");
+
+ [ObservableProperty]
+ private TimeSpan? notBeforeTimespan;
+
+ [ObservableProperty]
+ public bool hasActivationDateChecked;
+
+ [ObservableProperty]
+ public bool hasExpirationDateChecked;
+
+ public EditCertificateVersionViewModel()
+ {
+ _authService = Defaults.Locator.GetRequiredService();
+ _vaultService = Defaults.Locator.GetRequiredService();
+ _notificationViewModel = Defaults.Locator.GetRequiredService();
+ }
+
+ // Delegate to get updated tags from the UI
+ public Func>? GetUpdatedTags { get; set; }
+
+ public string? Identifier => KeyVaultCertificateModel?.Id?.ToString();
+ public string? Location => KeyVaultCertificateModel?.VaultUri.ToString();
+
+ [RelayCommand]
+ public async Task EditDetails()
+ {
+ // For certificates, we can only update tags and enabled status
+ // Date properties are typically managed by the certificate lifecycle
+
+ // Update tags from the TagsEditor if available
+ UpdateTagsFromEditor();
+
+ var updatedCert = await _vaultService.UpdateCertificate(KeyVaultCertificateModel, KeyVaultCertificateModel.VaultUri);
+ KeyVaultCertificateModel = updatedCert;
+ }
+
+ private void UpdateTagsFromEditor()
+ {
+ if (GetUpdatedTags != null)
+ {
+ var updatedTags = GetUpdatedTags();
+ KeyVaultCertificateModel.Tags.Clear();
+ foreach (var tag in updatedTags)
+ {
+ KeyVaultCertificateModel.Tags[tag.Key] = tag.Value;
+ }
+ }
+ }
+
+ partial void OnKeyVaultCertificateModelChanging(CertificateProperties value)
+ {
+ if (value != null)
+ {
+ HasActivationDateChecked = value.NotBefore.HasValue;
+ HasExpirationDateChecked = value.ExpiresOn.HasValue;
+ ExpiresOnTimespan = value.ExpiresOn.HasValue ? value.ExpiresOn.Value.LocalDateTime.TimeOfDay : null;
+ NotBeforeTimespan = value.NotBefore.HasValue ? value.NotBefore.Value.LocalDateTime.TimeOfDay : null;
+ }
+ }
+
+ partial void OnHasActivationDateCheckedChanged(bool oldValue, bool newValue)
+ {
+ // Certificate dates are usually managed automatically
+ // This might not be applicable for certificates
+ }
+
+ partial void OnHasExpirationDateCheckedChanged(bool oldValue, bool newValue)
+ {
+ // Certificate dates are usually managed automatically
+ // This might not be applicable for certificates
+ }
+}
\ No newline at end of file
diff --git a/KeyVaultExplorer/ViewModels/EditKeyVersionViewModel.cs b/KeyVaultExplorer/ViewModels/EditKeyVersionViewModel.cs
new file mode 100644
index 0000000..4fb0abd
--- /dev/null
+++ b/KeyVaultExplorer/ViewModels/EditKeyVersionViewModel.cs
@@ -0,0 +1,107 @@
+using Azure.Security.KeyVault.Keys;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using KeyVaultExplorer.Services;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace KeyVaultExplorer.ViewModels;
+
+public partial class EditKeyVersionViewModel : ViewModelBase
+{
+ private readonly AuthService _authService;
+ private readonly VaultService _vaultService;
+ private readonly NotificationViewModel _notificationViewModel;
+
+ [ObservableProperty]
+ private TimeSpan? expiresOnTimespan;
+
+ [ObservableProperty]
+ private bool isBusy = false;
+
+ [ObservableProperty]
+ private KeyProperties keyVaultKeyModel = new KeyProperties("");
+
+ [ObservableProperty]
+ private TimeSpan? notBeforeTimespan;
+
+ [ObservableProperty]
+ public bool hasActivationDateChecked;
+
+ [ObservableProperty]
+ public bool hasExpirationDateChecked;
+
+ public EditKeyVersionViewModel()
+ {
+ _authService = Defaults.Locator.GetRequiredService();
+ _vaultService = Defaults.Locator.GetRequiredService();
+ _notificationViewModel = Defaults.Locator.GetRequiredService();
+ }
+
+ // Delegate to get updated tags from the UI
+ public Func>? GetUpdatedTags { get; set; }
+
+ public string? Identifier => KeyVaultKeyModel?.Id?.ToString();
+ public string? Location => KeyVaultKeyModel?.VaultUri.ToString();
+
+ [RelayCommand]
+ public async Task EditDetails()
+ {
+ if (KeyVaultKeyModel.NotBefore.HasValue && HasActivationDateChecked)
+ KeyVaultKeyModel.NotBefore = KeyVaultKeyModel.NotBefore.Value.Date + (NotBeforeTimespan ?? TimeSpan.Zero);
+ else
+ KeyVaultKeyModel.NotBefore = null;
+
+ if (KeyVaultKeyModel.ExpiresOn.HasValue && HasExpirationDateChecked)
+ KeyVaultKeyModel.ExpiresOn = KeyVaultKeyModel.ExpiresOn.Value.Date + (ExpiresOnTimespan ?? TimeSpan.Zero);
+ else
+ KeyVaultKeyModel.ExpiresOn = null;
+
+ // Update tags from the TagsEditor if available
+ UpdateTagsFromEditor();
+
+ var updatedKey = await _vaultService.UpdateKey(KeyVaultKeyModel, KeyVaultKeyModel.VaultUri);
+ KeyVaultKeyModel = updatedKey.Properties;
+ }
+
+ private void UpdateTagsFromEditor()
+ {
+ if (GetUpdatedTags != null)
+ {
+ var updatedTags = GetUpdatedTags();
+ KeyVaultKeyModel.Tags.Clear();
+ foreach (var tag in updatedTags)
+ {
+ KeyVaultKeyModel.Tags[tag.Key] = tag.Value;
+ }
+ }
+ }
+
+ partial void OnKeyVaultKeyModelChanging(KeyProperties value)
+ {
+ if (value != null)
+ {
+ HasActivationDateChecked = value.NotBefore.HasValue;
+ HasExpirationDateChecked = value.ExpiresOn.HasValue;
+ ExpiresOnTimespan = value.ExpiresOn.HasValue ? value.ExpiresOn.Value.LocalDateTime.TimeOfDay : null;
+ NotBeforeTimespan = value.NotBefore.HasValue ? value.NotBefore.Value.LocalDateTime.TimeOfDay : null;
+ }
+ }
+
+ partial void OnHasActivationDateCheckedChanged(bool oldValue, bool newValue)
+ {
+ if (newValue is false)
+ {
+ KeyVaultKeyModel.NotBefore = null;
+ }
+ }
+
+ partial void OnHasExpirationDateCheckedChanged(bool oldValue, bool newValue)
+ {
+ if (newValue is false)
+ {
+ KeyVaultKeyModel.ExpiresOn = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/KeyVaultExplorer/ViewModels/PropertiesPageViewModel.cs b/KeyVaultExplorer/ViewModels/PropertiesPageViewModel.cs
index 070c740..a3002c3 100644
--- a/KeyVaultExplorer/ViewModels/PropertiesPageViewModel.cs
+++ b/KeyVaultExplorer/ViewModels/PropertiesPageViewModel.cs
@@ -238,6 +238,72 @@ private async Task EditVersion()
DataContext = viewModel
};
}
+ else if (IsKey)
+ {
+ var currentItem = KeyPropertiesList.OrderByDescending(x => x.CreatedOn).First();
+ var viewModel = new EditKeyVersionViewModel();
+
+ viewModel.KeyVaultKeyModel = currentItem;
+ dialog.PrimaryButtonClick += async (sender, args) =>
+ {
+ var def = args.GetDeferral();
+ try
+ {
+ await viewModel.EditDetailsCommand.ExecuteAsync(null);
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification("Success", "The key properties have been updated."));
+ }
+ catch (KeyVaultInsufficientPrivilegesException ex)
+ {
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Insufficient Privileges" });
+ }
+ catch (Exception ex)
+ {
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Error" });
+ }
+ finally
+ {
+ def.Complete();
+ }
+ };
+
+ dialog.Content = new EditKeyVersion()
+ {
+ DataContext = viewModel
+ };
+ }
+ else if (IsCertificate)
+ {
+ var currentItem = CertificatePropertiesList.OrderByDescending(x => x.CreatedOn).First();
+ var viewModel = new EditCertificateVersionViewModel();
+
+ viewModel.KeyVaultCertificateModel = currentItem;
+ dialog.PrimaryButtonClick += async (sender, args) =>
+ {
+ var def = args.GetDeferral();
+ try
+ {
+ await viewModel.EditDetailsCommand.ExecuteAsync(null);
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification("Success", "The certificate properties have been updated."));
+ }
+ catch (KeyVaultInsufficientPrivilegesException ex)
+ {
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Insufficient Privileges" });
+ }
+ catch (Exception ex)
+ {
+ _notificationViewModel.ShowPopup(new Avalonia.Controls.Notifications.Notification { Message = ex.Message, Title = "Error" });
+ }
+ finally
+ {
+ def.Complete();
+ }
+ };
+
+ dialog.Content = new EditCertificateVersion()
+ {
+ DataContext = viewModel
+ };
+ }
var result = await dialog.ShowAsync();
}
catch (KeyVaultItemNotFoundException ex)
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml
new file mode 100644
index 0000000..6f3e8e8
--- /dev/null
+++ b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml.cs b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml.cs
new file mode 100644
index 0000000..bd91099
--- /dev/null
+++ b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditCertificateVersion.axaml.cs
@@ -0,0 +1,47 @@
+using Avalonia.Controls;
+using KeyVaultExplorer.ViewModels;
+using System;
+using System.ComponentModel;
+
+namespace KeyVaultExplorer;
+
+public partial class EditCertificateVersion : UserControl
+{
+ public EditCertificateVersion()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnDataContextChanged(EventArgs e)
+ {
+ base.OnDataContextChanged(e);
+
+ if (DataContext is EditCertificateVersionViewModel vm)
+ {
+ // Wire up the delegate to get tags from the TagsEditor
+ vm.GetUpdatedTags = () => TagsEditor.TagsDictionary;
+
+ // Subscribe to ViewModel property changes to sync tags
+ vm.PropertyChanged += OnViewModelPropertyChanged;
+
+ // Initialize tags if KeyVaultCertificateModel is already set
+ if (vm.KeyVaultCertificateModel?.Tags != null)
+ {
+ TagsEditor.TagsDictionary = vm.KeyVaultCertificateModel.Tags;
+ }
+ }
+ }
+
+ private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(EditCertificateVersionViewModel.KeyVaultCertificateModel) &&
+ DataContext is EditCertificateVersionViewModel vm)
+ {
+ // Update TagsEditor when KeyVaultCertificateModel changes
+ if (vm.KeyVaultCertificateModel?.Tags != null)
+ {
+ TagsEditor.TagsDictionary = vm.KeyVaultCertificateModel.Tags;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml
new file mode 100644
index 0000000..0c8d429
--- /dev/null
+++ b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Set Activation Date
+
+
+
+
+
+
+ Set Expiration Date
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml.cs b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml.cs
new file mode 100644
index 0000000..340188b
--- /dev/null
+++ b/KeyVaultExplorer/Views/Pages/PropertiesDialogs/EditKeyVersion.axaml.cs
@@ -0,0 +1,47 @@
+using Avalonia.Controls;
+using KeyVaultExplorer.ViewModels;
+using System;
+using System.ComponentModel;
+
+namespace KeyVaultExplorer;
+
+public partial class EditKeyVersion : UserControl
+{
+ public EditKeyVersion()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnDataContextChanged(EventArgs e)
+ {
+ base.OnDataContextChanged(e);
+
+ if (DataContext is EditKeyVersionViewModel vm)
+ {
+ // Wire up the delegate to get tags from the TagsEditor
+ vm.GetUpdatedTags = () => TagsEditor.TagsDictionary;
+
+ // Subscribe to ViewModel property changes to sync tags
+ vm.PropertyChanged += OnViewModelPropertyChanged;
+
+ // Initialize tags if KeyVaultKeyModel is already set
+ if (vm.KeyVaultKeyModel?.Tags != null)
+ {
+ TagsEditor.TagsDictionary = vm.KeyVaultKeyModel.Tags;
+ }
+ }
+ }
+
+ private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(EditKeyVersionViewModel.KeyVaultKeyModel) &&
+ DataContext is EditKeyVersionViewModel vm)
+ {
+ // Update TagsEditor when KeyVaultKeyModel changes
+ if (vm.KeyVaultKeyModel?.Tags != null)
+ {
+ TagsEditor.TagsDictionary = vm.KeyVaultKeyModel.Tags;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/KeyVaultExplorer/Views/Pages/PropertiesPage.axaml b/KeyVaultExplorer/Views/Pages/PropertiesPage.axaml
index 36dd879..3ab4d58 100644
--- a/KeyVaultExplorer/Views/Pages/PropertiesPage.axaml
+++ b/KeyVaultExplorer/Views/Pages/PropertiesPage.axaml
@@ -86,7 +86,6 @@
Command="{Binding EditVersionCommand}"
IconSource="Edit"
IsEnabled="{Binding !IsManaged}"
- IsVisible="{Binding IsSecret}"
Label="Edit"
ToolTip.Tip="Edit Current Version"
ToolTip.VerticalOffset="10" />
From 7880abcde7d99eeafc5ee7d9bbca198243e7bc29 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 20 Aug 2025 12:00:35 +0000
Subject: [PATCH 5/5] Restore original .NET 9.0 target framework and finalize
tags editing implementation
Co-authored-by: cricketthomas <15821271+cricketthomas@users.noreply.github.com>
---
Desktop/Desktop.csproj | 4 ++--
KeyVaultExplorer/KeyVaultExplorer.csproj | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Desktop/Desktop.csproj b/Desktop/Desktop.csproj
index a0b1345..b4e4180 100644
--- a/Desktop/Desktop.csproj
+++ b/Desktop/Desktop.csproj
@@ -3,9 +3,9 @@
WinExe
- net8.0
+ net9.0
- $(TargetFrameworks);net8.0-windows10.0.19041.0
+ $(TargetFrameworks);net9.0-windows10.0.19041.0
10.0.19041.41
enable
diff --git a/KeyVaultExplorer/KeyVaultExplorer.csproj b/KeyVaultExplorer/KeyVaultExplorer.csproj
index 3ed8295..263decf 100644
--- a/KeyVaultExplorer/KeyVaultExplorer.csproj
+++ b/KeyVaultExplorer/KeyVaultExplorer.csproj
@@ -1,7 +1,7 @@
- net8.0
- $(TargetFrameworks);net8.0-windows10.0.19041.0
+ net9.0
+ $(TargetFrameworks);net9.0-windows10.0.19041.0
10.0.19041.41