diff --git a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
index 0fab2d93cb..26d80cd94c 100644
--- a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
+++ b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
@@ -13,40 +13,17 @@
};
}
-@if (IconEnd is not null)
-{
-
-}
-else
-{
-
-}
+
@foreach (var item in Items)
diff --git a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
index cb944ac19c..52e38fac71 100644
--- a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
+++ b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
@@ -22,9 +22,6 @@ public partial class AspireMenuButton : FluentComponentBase
[Parameter]
public Icon? IconStart { get; set; }
- [Parameter]
- public Icon? IconEnd { get; set; }
-
[Parameter]
public Icon? Icon { get; set; }
@@ -43,8 +40,7 @@ public partial class AspireMenuButton : FluentComponentBase
[Parameter]
public string? Title { get; set; }
- [Parameter]
- public string MenuButtonId { get; set; } = Identifier.NewId();
+ public string MenuButtonId { get; } = Identifier.NewId();
protected override void OnParametersSet()
{
diff --git a/src/Aspire.Dashboard/Components/Pages/Resources.razor b/src/Aspire.Dashboard/Components/Pages/Resources.razor
index 48bd238922..5fd10474ba 100644
--- a/src/Aspire.Dashboard/Components/Pages/Resources.razor
+++ b/src/Aspire.Dashboard/Components/Pages/Resources.razor
@@ -43,7 +43,7 @@
@if (HasAnyChildResources())
{
@@ -53,7 +53,7 @@
{
@if (HasAnyChildResources())
{
- var showExpandAllButton = _collapsedResourceNames.Count > 0;
+ var showExpandAllButton = HasCollapsedResources();
diff --git a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
index 28296dfd05..8534e9b738 100644
--- a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
+++ b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
@@ -45,7 +45,7 @@ public partial class Resources : ComponentBase, IAsyncDisposable
[Inject]
public required IJSRuntime JS { get; init; }
[Inject]
- public required ILocalStorage LocalStorage { get; init; }
+ public required ISessionStorage SessionStorage { get; init; }
[CascadingParameter]
public required ViewportInformation ViewportInformation { get; set; }
@@ -71,7 +71,6 @@ public partial class Resources : ComponentBase, IAsyncDisposable
private readonly CancellationTokenSource _watchTaskCancellationTokenSource = new();
private readonly ConcurrentDictionary _resourceByName = new(StringComparers.ResourceName);
private readonly HashSet _collapsedResourceNames = new(StringComparers.ResourceName);
- private readonly HashSet _initialCollapsedResourceNames = [];
private string _filter = "";
private bool _isFilterPopupVisible;
private Task? _resourceSubscriptionTask;
@@ -153,12 +152,12 @@ protected override async Task OnInitializedAsync()
if (DashboardClient.IsEnabled)
{
- var settings = await LocalStorage.GetUnprotectedAsync(BrowserStorageKeys.ResourcesPageSettings);
- if (settings.Value is not null)
+ var collapsedResult = await SessionStorage.GetAsync>(BrowserStorageKeys.ResourcesCollapsedResourceNames);
+ if (collapsedResult.Success)
{
- foreach (var resourceName in settings.Value.CollapsedResourceNames)
+ foreach (var resourceName in collapsedResult.Value)
{
- _initialCollapsedResourceNames.Add(resourceName);
+ _collapsedResourceNames.Add(resourceName);
}
}
@@ -265,11 +264,6 @@ bool UpdateFromResource(ResourceViewModel resource, Func resourceT
ResourceStatesToVisibility.TryAdd(resource.State ?? string.Empty, stateVisible(resource.State ?? string.Empty));
ResourceHealthStatusesToVisibility.TryAdd(resource.HealthStatus?.Humanize() ?? string.Empty, healthStatusVisible(resource.HealthStatus?.Humanize() ?? string.Empty));
- if (_initialCollapsedResourceNames.Contains(resource.Name))
- {
- _collapsedResourceNames.Add(resource.Name);
- }
-
UpdateMenuButtons();
return added;
@@ -311,7 +305,7 @@ private void UpdateMenuButtons()
{
_resourcesMenuItems.Clear();
- if (_collapsedResourceNames.Count > 0)
+ if (HasCollapsedResources())
{
_resourcesMenuItems.Add(new MenuButtonItem
{
@@ -333,6 +327,11 @@ private void UpdateMenuButtons()
}
}
+ private bool HasCollapsedResources()
+ {
+ return _resourceByName.Any(r => !r.Value.IsHiddenState() && _collapsedResourceNames.Contains(r.Key));
+ }
+
private void UpdateMaxHighlightedCount()
{
var maxHighlightedCount = 0;
@@ -505,26 +504,34 @@ private async Task OnToggleCollapse(ResourceGridViewModel viewModel)
_collapsedResourceNames.Remove(viewModel.Resource.Name);
}
- await LocalStorage.SetUnprotectedAsync(BrowserStorageKeys.ResourcesPageSettings, new ResourcesPageSettings(CollapsedResourceNames: _collapsedResourceNames));
+ await SessionStorage.SetAsync(BrowserStorageKeys.ResourcesCollapsedResourceNames, _collapsedResourceNames.ToList());
await _dataGrid.SafeRefreshDataAsync();
UpdateMenuButtons();
}
private async Task OnToggleCollapseAll()
{
- if (_collapsedResourceNames.Count > 0)
+ var resourcesWithChildren = _resourceByName.Values
+ .Where(r => !r.IsHiddenState())
+ .Where(r => _resourceByName.Values.Any(nested => nested.GetResourcePropertyValue(KnownProperties.Resource.ParentName) == r.Name))
+ .ToList();
+
+ if (HasCollapsedResources())
{
- _collapsedResourceNames.Clear();
+ foreach (var resource in resourcesWithChildren)
+ {
+ _collapsedResourceNames.Remove(resource.Name);
+ }
}
else
{
- foreach (var resourceName in _resourceByName.Keys)
+ foreach (var resource in resourcesWithChildren)
{
- _collapsedResourceNames.Add(resourceName);
+ _collapsedResourceNames.Add(resource.Name);
}
}
- await LocalStorage.SetUnprotectedAsync(BrowserStorageKeys.ResourcesPageSettings, new ResourcesPageSettings(CollapsedResourceNames: _collapsedResourceNames));
+ await SessionStorage.SetAsync(BrowserStorageKeys.ResourcesCollapsedResourceNames, _collapsedResourceNames.ToList());
await _dataGrid.SafeRefreshDataAsync();
UpdateMenuButtons();
}
@@ -547,6 +554,4 @@ public async ValueTask DisposeAsync()
await TaskHelpers.WaitIgnoreCancelAsync(_resourceSubscriptionTask);
}
-
- public record ResourcesPageSettings(HashSet CollapsedResourceNames);
}
diff --git a/src/Aspire.Dashboard/Model/BrowserStorage/StorageResult.cs b/src/Aspire.Dashboard/Model/BrowserStorage/StorageResult.cs
index 23a7849922..9cc9d3411f 100644
--- a/src/Aspire.Dashboard/Model/BrowserStorage/StorageResult.cs
+++ b/src/Aspire.Dashboard/Model/BrowserStorage/StorageResult.cs
@@ -1,6 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace Aspire.Dashboard.Model.BrowserStorage;
-public readonly record struct StorageResult(bool Success, TValue? Value);
+public readonly struct StorageResult
+{
+ [MemberNotNullWhen(true, nameof(Value))]
+ public bool Success { get; }
+
+ public TValue? Value { get; }
+
+ public StorageResult(bool success, TValue? value)
+ {
+ Success = success;
+ Value = value;
+ }
+}
diff --git a/src/Aspire.Dashboard/Resources/Resources.Designer.cs b/src/Aspire.Dashboard/Resources/Resources.Designer.cs
index 6b5af112f9..adfcb3160b 100644
--- a/src/Aspire.Dashboard/Resources/Resources.Designer.cs
+++ b/src/Aspire.Dashboard/Resources/Resources.Designer.cs
@@ -1,6 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -384,7 +385,7 @@ public static string ResourcesEnvironmentVariablesHeader {
}
///
- /// Looks up a localized string similar to Update filters.
+ /// Looks up a localized string similar to Has filters.
///
public static string ResourcesFiltered {
get {
@@ -420,7 +421,7 @@ public static string ResourcesNoResources {
}
///
- /// Looks up a localized string similar to Add filters.
+ /// Looks up a localized string similar to No filters.
///
public static string ResourcesNotFiltered {
get {
diff --git a/src/Aspire.Dashboard/Resources/Resources.resx b/src/Aspire.Dashboard/Resources/Resources.resx
index 3985d5bd9f..4627b62367 100644
--- a/src/Aspire.Dashboard/Resources/Resources.resx
+++ b/src/Aspire.Dashboard/Resources/Resources.resx
@@ -1,17 +1,17 @@
-
@@ -125,10 +125,10 @@
Resources
- Add filters
+ No filters
- Update filters
+ Has filters
Resource types
@@ -274,4 +274,4 @@
Expand child resources
-
+
\ No newline at end of file
diff --git a/src/Aspire.Dashboard/Utils/BrowserStorageKeys.cs b/src/Aspire.Dashboard/Utils/BrowserStorageKeys.cs
index b3460c328a..f41dec6052 100644
--- a/src/Aspire.Dashboard/Utils/BrowserStorageKeys.cs
+++ b/src/Aspire.Dashboard/Utils/BrowserStorageKeys.cs
@@ -14,7 +14,7 @@ internal static class BrowserStorageKeys
public const string MetricsPageState = "Aspire_PageState_Metrics";
public const string ConsoleLogsPageState = "Aspire_PageState_ConsoleLogs";
public const string ConsoleLogConsoleSettings = "Aspire_ConsoleLog_ConsoleSettings";
- public const string ResourcesPageSettings = "Aspire_Resources_ResourcesPageSettings";
+ public const string ResourcesCollapsedResourceNames = "Aspire_Resources_CollapsedResourceNames";
public static string SplitterOrientationKey(string viewKey)
{
diff --git a/tests/Aspire.Dashboard.Components.Tests/Shared/TestLocalStorage.cs b/tests/Aspire.Dashboard.Components.Tests/Shared/TestLocalStorage.cs
index 96b29fc590..eab5a6ac7d 100644
--- a/tests/Aspire.Dashboard.Components.Tests/Shared/TestLocalStorage.cs
+++ b/tests/Aspire.Dashboard.Components.Tests/Shared/TestLocalStorage.cs
@@ -12,7 +12,7 @@ public sealed class TestLocalStorage : ILocalStorage
public Task> GetAsync(string key)
{
- return Task.FromResult(new StorageResult(Success: false, Value: default));
+ return Task.FromResult(new StorageResult(success: false, value: default));
}
public Task> GetUnprotectedAsync(string key)
@@ -20,9 +20,9 @@ public Task> GetUnprotectedAsync(string key)
if (OnGetUnprotectedAsync is { } callback)
{
var (success, value) = callback(key);
- return Task.FromResult(new StorageResult(Success: success, Value: (T)(value ?? default(T))!));
+ return Task.FromResult(new StorageResult(success: success, value: (T)(value ?? default(T))!));
}
- return Task.FromResult(new StorageResult(Success: false, Value: default));
+ return Task.FromResult(new StorageResult(success: false, value: default));
}
public Task SetAsync(string key, T value)
diff --git a/tests/Aspire.Dashboard.Components.Tests/Shared/TestSessionStorage.cs b/tests/Aspire.Dashboard.Components.Tests/Shared/TestSessionStorage.cs
index 9f01691d77..678c64ea57 100644
--- a/tests/Aspire.Dashboard.Components.Tests/Shared/TestSessionStorage.cs
+++ b/tests/Aspire.Dashboard.Components.Tests/Shared/TestSessionStorage.cs
@@ -15,10 +15,10 @@ public Task> GetAsync(string key)
if (OnGetAsync is { } callback)
{
var (success, value) = callback(key);
- return Task.FromResult(new StorageResult(Success: success, Value: (T)(value ?? default(T))!));
+ return Task.FromResult(new StorageResult(success: success, value: (T)(value ?? default(T))!));
}
- return Task.FromResult>(new StorageResult(Success: false, Value: default));
+ return Task.FromResult>(new StorageResult(success: false, value: default));
}
public Task SetAsync(string key, T value)