diff --git a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
index 7c4881dda7a..b60f7831436 100644
--- a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
+++ b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor
@@ -21,7 +21,11 @@
else
{
@Text
-
+
+ @if (!HideIcon)
+ {
+
+ }
}
@@ -36,10 +40,10 @@
{
var additionalMenuItemAttributes = new Dictionary(item.AdditionalAttributes ?? ImmutableDictionary.Empty)
{
- { "title", item.Tooltip ?? string.Empty }
+ { "title", item.Tooltip ?? item.Text ?? string.Empty }
};
-
+
@item.Text
@if (item.Icon != null)
{
diff --git a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
index 3463d32d5a7..54c063c8467 100644
--- a/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
+++ b/src/Aspire.Dashboard/Components/Controls/AspireMenuButton.razor.cs
@@ -43,6 +43,9 @@ public partial class AspireMenuButton : FluentComponentBase
[Parameter]
public string MenuButtonId { get; set; } = Identifier.NewId();
+ [Parameter]
+ public bool HideIcon { get; set; }
+
protected override void OnParametersSet()
{
_icon = Icon ?? s_defaultIcon;
diff --git a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
index 2c129c76319..83709331680 100644
--- a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
+++ b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor
@@ -6,6 +6,7 @@
@using Aspire.Dashboard.Resources
@using System.Globalization
@using Aspire.Dashboard.Components.Controls.Grid
+@using Aspire.Dashboard.Model
@inject IJSRuntime JS
@implements IDisposable
@@ -68,22 +69,17 @@
HandleSelectedLogLevelChangedAsync="@HandleSelectedLogLevelChangedAsync" />
}
- @FilterLoc[nameof(StructuredFiltering.Filters)]
@if (ViewModel.Filters.Count == 0)
{
@FilterLoc[nameof(StructuredFiltering.NoFilters)]
}
else
{
- for (var i = 0; i < ViewModel.Filters.Count; i++)
- {
- var filter = ViewModel.Filters[i];
- if (i != 0)
- {
-
- }
- @filter.GetDisplayText(FilterLoc)
- }
+
}
@if (ViewportInformation.IsDesktop)
diff --git a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs
index 6a914209112..aca17fd1365 100644
--- a/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs
+++ b/src/Aspire.Dashboard/Components/Pages/StructuredLogs.razor.cs
@@ -349,6 +349,39 @@ private string GetRowClass(OtlpLogEntry entry)
}
}
+ private List GetFilterMenuItems()
+ {
+ var filterMenuItems = new List();
+
+ foreach (var filter in ViewModel.Filters)
+ {
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ OnClick = () => OpenFilterAsync(filter),
+ Text = filter.GetDisplayText(FilterLoc),
+ Class = "filter-menu-item",
+ });
+ }
+
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ IsDivider = true
+ });
+
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ Text = DialogsLoc[nameof(Dashboard.Resources.Dialogs.SettingsRemoveAllButtonText)],
+ Icon = new Microsoft.FluentUI.AspNetCore.Components.Icons.Regular.Size16.Delete(),
+ OnClick = () =>
+ {
+ ViewModel.ClearFilters();
+ return this.AfterViewModelChangedAsync(_contentLayout, waitToApplyMobileChange: false);
+ }
+ });
+
+ return filterMenuItems;
+ }
+
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (_applicationChanged)
diff --git a/src/Aspire.Dashboard/Components/Pages/Traces.razor b/src/Aspire.Dashboard/Components/Pages/Traces.razor
index 2c76c270189..7984a0c462d 100644
--- a/src/Aspire.Dashboard/Components/Pages/Traces.razor
+++ b/src/Aspire.Dashboard/Components/Pages/Traces.razor
@@ -47,22 +47,17 @@
title="@Loc[nameof(Dashboard.Resources.Traces.TracesNameFilter)]"
slot="end" />
- @FilterLoc[nameof(StructuredFiltering.Filters)]
@if (TracesViewModel.Filters.Count == 0)
{
@FilterLoc[nameof(StructuredFiltering.NoFilters)]
}
else
{
- for (var i = 0; i < TracesViewModel.Filters.Count; i++)
- {
- var filter = TracesViewModel.Filters[i];
- if (i != 0)
- {
-
- }
- @filter.GetDisplayText(FilterLoc)
- }
+
}
@if (ViewportInformation.IsDesktop)
diff --git a/src/Aspire.Dashboard/Components/Pages/Traces.razor.cs b/src/Aspire.Dashboard/Components/Pages/Traces.razor.cs
index 9619c8a9faf..d7ab137de73 100644
--- a/src/Aspire.Dashboard/Components/Pages/Traces.razor.cs
+++ b/src/Aspire.Dashboard/Components/Pages/Traces.razor.cs
@@ -343,6 +343,39 @@ private Task ClearTraces(ApplicationKey? key)
return Task.CompletedTask;
}
+ private List GetFilterMenuItems()
+ {
+ var filterMenuItems = new List();
+
+ foreach (var filter in TracesViewModel.Filters)
+ {
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ OnClick = () => OpenFilterAsync(filter),
+ Text = filter.GetDisplayText(FilterLoc),
+ Class = "filter-menu-item",
+ });
+ }
+
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ IsDivider = true
+ });
+
+ filterMenuItems.Add(new MenuButtonItem
+ {
+ Text = DialogsLoc[nameof(Dashboard.Resources.Dialogs.SettingsRemoveAllButtonText)],
+ Icon = new Microsoft.FluentUI.AspNetCore.Components.Icons.Regular.Size16.Delete(),
+ OnClick = () =>
+ {
+ TracesViewModel.ClearFilters();
+ return this.AfterViewModelChangedAsync(_contentLayout, waitToApplyMobileChange: false);
+ }
+ });
+
+ return filterMenuItems;
+ }
+
public class TracesPageViewModel
{
public required SelectViewModel SelectedApplication { get; set; }
diff --git a/src/Aspire.Dashboard/Model/MenuButtonItem.cs b/src/Aspire.Dashboard/Model/MenuButtonItem.cs
index 174e836636b..57b254733af 100644
--- a/src/Aspire.Dashboard/Model/MenuButtonItem.cs
+++ b/src/Aspire.Dashboard/Model/MenuButtonItem.cs
@@ -14,5 +14,6 @@ public class MenuButtonItem
public Func? OnClick { get; set; }
public bool IsDisabled { get; set; }
public string Id { get; set; } = Identifier.NewId();
+ public string? Class { get; set; }
public IReadOnlyDictionary? AdditionalAttributes { get; set; }
}
diff --git a/src/Aspire.Dashboard/wwwroot/css/app.css b/src/Aspire.Dashboard/wwwroot/css/app.css
index 500db7a7ed4..35bcf66b4a8 100644
--- a/src/Aspire.Dashboard/wwwroot/css/app.css
+++ b/src/Aspire.Dashboard/wwwroot/css/app.css
@@ -535,12 +535,6 @@ fluent-switch.table-switch::part(label) {
padding: calc(((var(--design-unit) * 0.5) - var(--stroke-width)) * 1px) calc((var(--design-unit) - var(--stroke-width)) * 1px);
}
-.telemetry-filter-button::part(content) {
- max-width: 350px;
- overflow: hidden;
- text-overflow: ellipsis
-}
-
.mobile-toolbar {
width: 100%;
height: max(5vh, 30px);
@@ -752,3 +746,7 @@ fluent-switch.table-switch::part(label) {
max-height: 400px;
overflow-y: auto;
}
+
+.filter-menu-item::part(content) {
+ max-width: 300px;
+}
diff --git a/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs b/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs
index 99777f0bf64..d273a4e8e03 100644
--- a/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs
+++ b/tests/Aspire.Dashboard.Components.Tests/Pages/StructuredLogsTests.cs
@@ -189,6 +189,7 @@ private void SetupStructureLogsServices()
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
+ Services.AddSingleton();
}
private static string GetFluentFile(string filePath, Version version)
diff --git a/tests/Shared/AsyncTestHelpers.cs b/tests/Shared/AsyncTestHelpers.cs
index 785a9efdc22..62640fc0048 100644
--- a/tests/Shared/AsyncTestHelpers.cs
+++ b/tests/Shared/AsyncTestHelpers.cs
@@ -182,7 +182,7 @@ public static async Task AssertIsTrueRetryAsync(Func> assert, string
{
if (i > 0)
{
- await Task.Delay((i + 1) * (i + 1) * 10);
+ await Task.Delay((i + 1) * (i + 1) * 10 * 5);
}
if (await assert())