diff --git a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor
index f9fe8557abe..76d09177be7 100644
--- a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor
+++ b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor
@@ -8,11 +8,10 @@
-
+
@@ -21,34 +20,42 @@
AriaLabel="@ControlsStringsLoc[nameof(ControlsStrings.ResourceLabel)]"
@bind-SelectedResource="PageViewModel.SelectedOption"
@bind-SelectedResource:after="HandleSelectedOptionChangedAsync" />
- @if (ViewportInformation.IsDesktop)
- {
- // This takes up too much horizontal space on mobile, so show on a new line on mobile
- @PageViewModel.Status
- }
- @{
- var menuItems = new List
- {
- new()
+ @foreach (var command in _highlightedCommands)
+ {
+
+ @if (!string.IsNullOrEmpty(command.IconName) && CommandViewModel.ResolveIconName(command.IconName, command.IconVariant) is { } icon)
+ {
+
+ }
+ else
{
- IsDisabled = PageViewModel.SelectedResource is null,
- OnClick = DownloadLogsAsync,
- AdditionalAttributes = new Dictionary
- {
- { "data-action", "download" },
- { "data-resource", PageViewModel.SelectedResource?.Name ?? string.Empty }
- },
- Text = Loc[nameof(Dashboard.Resources.ConsoleLogs.DownloadLogs)],
- Icon = new Icons.Regular.Size16.ArrowDownload()
+ @command.DisplayName
}
- };
+
+ }
+
+ @if (_resourceMenuItems.Count > 0)
+ {
+
+ }
+
+ @if (ViewportInformation.IsDesktop)
+ {
+ // This takes up too much horizontal space on mobile, so show on a new line on mobile
+ @PageViewModel.Status
}
diff --git a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
index 9696d99cd9e..a11299a3b45 100644
--- a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
+++ b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs
@@ -18,6 +18,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
+using Microsoft.FluentUI.AspNetCore.Components;
using Microsoft.JSInterop;
namespace Aspire.Dashboard.Components.Pages;
@@ -63,6 +64,9 @@ private sealed class ConsoleLogsSubscription
[Inject]
public required IJSRuntime JS { get; init; }
+ [Inject]
+ public required DashboardCommandExecutor DashboardCommandExecutor { get; init; }
+
[CascadingParameter]
public required ViewportInformation ViewportInformation { get; init; }
@@ -80,6 +84,9 @@ private sealed class ConsoleLogsSubscription
// UI
private SelectViewModel _noSelection = null!;
private AspirePageContentLayout? _contentLayout;
+ private readonly List _highlightedCommands = new();
+ private readonly List _logsMenuItems = new();
+ private readonly List _resourceMenuItems = new();
// State
public ConsoleLogsViewModel PageViewModel { get; set; } = null!;
@@ -166,6 +173,7 @@ async Task TrackResourceSnapshotsAsync()
}
}
+ UpdateMenuButtons();
await InvokeAsync(StateHasChanged);
}
});
@@ -191,6 +199,8 @@ protected override async Task OnParametersSetAsync()
return;
}
+ UpdateMenuButtons();
+
var selectedResourceName = PageViewModel.SelectedResource?.Name;
if (!string.Equals(selectedResourceName, _consoleLogsSubscription?.Name, StringComparisons.ResourceName))
{
@@ -234,6 +244,54 @@ protected override async Task OnParametersSetAsync()
}
}
+ private void UpdateMenuButtons()
+ {
+ _highlightedCommands.Clear();
+ _logsMenuItems.Clear();
+ _resourceMenuItems.Clear();
+
+ _logsMenuItems.Add(new()
+ {
+ IsDisabled = PageViewModel.SelectedResource is null,
+ OnClick = DownloadLogsAsync,
+ Text = Loc[nameof(Dashboard.Resources.ConsoleLogs.DownloadLogs)],
+ Icon = new Icons.Regular.Size16.ArrowDownload()
+ });
+
+ if (PageViewModel.SelectedResource != null)
+ {
+ if (ViewportInformation.IsDesktop)
+ {
+ _highlightedCommands.AddRange(PageViewModel.SelectedResource.Commands.Where(c => c.IsHighlighted && c.State != CommandViewModelState.Hidden).Take(DashboardUIHelpers.MaxHighlightedCommands));
+ }
+
+ var menuCommands = PageViewModel.SelectedResource.Commands.Where(c => !_highlightedCommands.Contains(c) && c.State != CommandViewModelState.Hidden).ToList();
+ if (menuCommands.Count > 0)
+ {
+ foreach (var command in menuCommands)
+ {
+ var icon = (!string.IsNullOrEmpty(command.IconName) && CommandViewModel.ResolveIconName(command.IconName, command.IconVariant) is { } i) ? i : null;
+
+ _resourceMenuItems.Add(new MenuButtonItem
+ {
+ Text = command.DisplayName,
+ Tooltip = command.DisplayDescription,
+ Icon = icon,
+ OnClick = () => ExecuteResourceCommandAsync(command),
+ IsDisabled = command.State == CommandViewModelState.Disabled
+ });
+ }
+ }
+ }
+ }
+
+ private async Task ExecuteResourceCommandAsync(CommandViewModel command)
+ {
+ await DashboardCommandExecutor.ExecuteAsync(PageViewModel.SelectedResource!, command, GetResourceName);
+ }
+
+ private string GetResourceName(ResourceViewModel resource) => ResourceViewModel.GetResourceName(resource, _resourceByName);
+
internal static ImmutableList> GetConsoleLogResourceSelectViewModels(
ConcurrentDictionary resourcesByName,
SelectViewModel noSelectionViewModel,
diff --git a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
index d35461e8b75..651748f9197 100644
--- a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
+++ b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
@@ -36,9 +36,7 @@ public partial class Resources : ComponentBase, IAsyncDisposable
[Inject]
public required NavigationManager NavigationManager { get; init; }
[Inject]
- public required IDialogService DialogService { get; init; }
- [Inject]
- public required IToastService ToastService { get; init; }
+ public required DashboardCommandExecutor DashboardCommandExecutor { get; init; }
[Inject]
public required BrowserTimeProvider TimeProvider { get; init; }
[Inject]
@@ -283,7 +281,7 @@ private void UpdateMaxHighlightedCount()
// Don't attempt to display more than 2 highlighted commands. Many commands will take up too much space.
// Extra highlighted commands are still available in the menu.
- _maxHighlightedCount = Math.Min(maxHighlightedCount, 2);
+ _maxHighlightedCount = Math.Min(maxHighlightedCount, DashboardUIHelpers.MaxHighlightedCommands);
}
protected override async Task OnParametersSetAsync()
@@ -394,68 +392,7 @@ private string GetRowClass(ResourceViewModel resource)
private async Task ExecuteResourceCommandAsync(ResourceViewModel resource, CommandViewModel command)
{
- if (!string.IsNullOrWhiteSpace(command.ConfirmationMessage))
- {
- var dialogReference = await DialogService.ShowConfirmationAsync(command.ConfirmationMessage);
- var result = await dialogReference.Result;
- if (result.Cancelled)
- {
- return;
- }
- }
-
- var messageResourceName = GetResourceName(resource);
-
- var toastParameters = new ToastParameters()
- {
- Id = Guid.NewGuid().ToString(),
- Intent = ToastIntent.Progress,
- Title = string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.Resources.ResourceCommandStarting)], messageResourceName, command.DisplayName),
- Content = new CommunicationToastContent()
- };
-
- // Show a toast immediately to indicate the command is starting.
- ToastService.ShowCommunicationToast(toastParameters);
-
- var response = await DashboardClient.ExecuteResourceCommandAsync(resource.Name, resource.ResourceType, command, CancellationToken.None);
-
- // Update toast with the result;
- if (response.Kind == ResourceCommandResponseKind.Succeeded)
- {
- toastParameters.Title = string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.Resources.ResourceCommandSuccess)], messageResourceName, command.DisplayName);
- toastParameters.Intent = ToastIntent.Success;
- toastParameters.Icon = GetIntentIcon(ToastIntent.Success);
- }
- else
- {
- toastParameters.Title = string.Format(CultureInfo.InvariantCulture, Loc[nameof(Dashboard.Resources.Resources.ResourceCommandFailed)], messageResourceName, command.DisplayName);
- toastParameters.Intent = ToastIntent.Error;
- toastParameters.Icon = GetIntentIcon(ToastIntent.Error);
- toastParameters.Content.Details = response.ErrorMessage;
- toastParameters.PrimaryAction = Loc[nameof(Dashboard.Resources.Resources.ResourceCommandToastViewLogs)];
- toastParameters.OnPrimaryAction = EventCallback.Factory.Create(this, () => NavigationManager.NavigateTo(DashboardUrls.ConsoleLogsUrl(resource: resource.Name)));
- }
-
- ToastService.UpdateToast(toastParameters.Id, toastParameters);
- }
-
- // Copied from FluentUI.
- private static (Icon Icon, Color Color)? GetIntentIcon(ToastIntent intent)
- {
- return intent switch
- {
- ToastIntent.Success => (new Icons.Filled.Size24.CheckmarkCircle(), Color.Success),
- ToastIntent.Warning => (new Icons.Filled.Size24.Warning(), Color.Warning),
- ToastIntent.Error => (new Icons.Filled.Size24.DismissCircle(), Color.Error),
- ToastIntent.Info => (new Icons.Filled.Size24.Info(), Color.Info),
- ToastIntent.Progress => (new Icons.Regular.Size24.Flash(), Color.Neutral),
- ToastIntent.Upload => (new Icons.Regular.Size24.ArrowUpload(), Color.Neutral),
- ToastIntent.Download => (new Icons.Regular.Size24.ArrowDownload(), Color.Neutral),
- ToastIntent.Event => (new Icons.Regular.Size24.CalendarLtr(), Color.Neutral),
- ToastIntent.Mention => (new Icons.Regular.Size24.Person(), Color.Neutral),
- ToastIntent.Custom => null,
- _ => throw new InvalidOperationException()
- };
+ await DashboardCommandExecutor.ExecuteAsync(resource, command, GetResourceName);
}
private static (string Value, string? ContentAfterValue, string ValueToCopy, string Tooltip)? GetSourceColumnValueAndTooltip(ResourceViewModel resource)
diff --git a/src/Aspire.Dashboard/DashboardWebApplication.cs b/src/Aspire.Dashboard/DashboardWebApplication.cs
index 6cd3dcae097..97ad8b58157 100644
--- a/src/Aspire.Dashboard/DashboardWebApplication.cs
+++ b/src/Aspire.Dashboard/DashboardWebApplication.cs
@@ -233,6 +233,7 @@ public DashboardWebApplication(
// Data from the server.
builder.Services.TryAddScoped();
builder.Services.TryAddSingleton();
+ builder.Services.TryAddScoped();
// OTLP services.
builder.Services.AddGrpc();
diff --git a/src/Aspire.Dashboard/Model/DashboardCommandExecutor.cs b/src/Aspire.Dashboard/Model/DashboardCommandExecutor.cs
new file mode 100644
index 00000000000..3a0bdb9b314
--- /dev/null
+++ b/src/Aspire.Dashboard/Model/DashboardCommandExecutor.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Globalization;
+using Aspire.Dashboard.Utils;
+using Microsoft.AspNetCore.Components;
+using Microsoft.Extensions.Localization;
+using Microsoft.FluentUI.AspNetCore.Components;
+
+namespace Aspire.Dashboard.Model;
+
+public sealed class DashboardCommandExecutor(
+ IDashboardClient dashboardClient,
+ IDialogService dialogService,
+ IToastService toastService,
+ IStringLocalizer loc,
+ NavigationManager navigationManager)
+{
+ public async Task ExecuteAsync(ResourceViewModel resource, CommandViewModel command, Func getResourceName)
+ {
+ if (!string.IsNullOrWhiteSpace(command.ConfirmationMessage))
+ {
+ var dialogReference = await dialogService.ShowConfirmationAsync(command.ConfirmationMessage).ConfigureAwait(false);
+ var result = await dialogReference.Result.ConfigureAwait(false);
+ if (result.Cancelled)
+ {
+ return;
+ }
+ }
+
+ var messageResourceName = getResourceName(resource);
+
+ var toastParameters = new ToastParameters()
+ {
+ Id = Guid.NewGuid().ToString(),
+ Intent = ToastIntent.Progress,
+ Title = string.Format(CultureInfo.InvariantCulture, loc[nameof(Dashboard.Resources.Resources.ResourceCommandStarting)], messageResourceName, command.DisplayName),
+ Content = new CommunicationToastContent()
+ };
+
+ // Show a toast immediately to indicate the command is starting.
+ toastService.ShowCommunicationToast(toastParameters);
+
+ var response = await dashboardClient.ExecuteResourceCommandAsync(resource.Name, resource.ResourceType, command, CancellationToken.None).ConfigureAwait(false);
+
+ // Update toast with the result;
+ if (response.Kind == ResourceCommandResponseKind.Succeeded)
+ {
+ toastParameters.Title = string.Format(CultureInfo.InvariantCulture, loc[nameof(Dashboard.Resources.Resources.ResourceCommandSuccess)], messageResourceName, command.DisplayName);
+ toastParameters.Intent = ToastIntent.Success;
+ toastParameters.Icon = GetIntentIcon(ToastIntent.Success);
+ }
+ else
+ {
+ toastParameters.Title = string.Format(CultureInfo.InvariantCulture, loc[nameof(Dashboard.Resources.Resources.ResourceCommandFailed)], messageResourceName, command.DisplayName);
+ toastParameters.Intent = ToastIntent.Error;
+ toastParameters.Icon = GetIntentIcon(ToastIntent.Error);
+ toastParameters.Content.Details = response.ErrorMessage;
+ toastParameters.PrimaryAction = loc[nameof(Dashboard.Resources.Resources.ResourceCommandToastViewLogs)];
+ toastParameters.OnPrimaryAction = EventCallback.Factory.Create(this, () => navigationManager.NavigateTo(DashboardUrls.ConsoleLogsUrl(resource: resource.Name)));
+ }
+
+ toastService.UpdateToast(toastParameters.Id, toastParameters);
+ }
+
+ // Copied from FluentUI.
+ private static (Icon Icon, Color Color)? GetIntentIcon(ToastIntent intent)
+ {
+ return intent switch
+ {
+ ToastIntent.Success => (new Icons.Filled.Size24.CheckmarkCircle(), Color.Success),
+ ToastIntent.Warning => (new Icons.Filled.Size24.Warning(), Color.Warning),
+ ToastIntent.Error => (new Icons.Filled.Size24.DismissCircle(), Color.Error),
+ ToastIntent.Info => (new Icons.Filled.Size24.Info(), Color.Info),
+ ToastIntent.Progress => (new Icons.Regular.Size24.Flash(), Color.Neutral),
+ ToastIntent.Upload => (new Icons.Regular.Size24.ArrowUpload(), Color.Neutral),
+ ToastIntent.Download => (new Icons.Regular.Size24.ArrowDownload(), Color.Neutral),
+ ToastIntent.Event => (new Icons.Regular.Size24.CalendarLtr(), Color.Neutral),
+ ToastIntent.Mention => (new Icons.Regular.Size24.Person(), Color.Neutral),
+ ToastIntent.Custom => null,
+ _ => throw new InvalidOperationException()
+ };
+ }
+}
diff --git a/src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs b/src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs
index 4f446147e70..b6fa1eea607 100644
--- a/src/Aspire.Dashboard/Resources/ConsoleLogs.Designer.cs
+++ b/src/Aspire.Dashboard/Resources/ConsoleLogs.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.
@@ -131,6 +132,15 @@ public static string ConsoleLogsPageTitle {
}
}
+ ///
+ /// Looks up a localized string similar to Resource commands.
+ ///
+ public static string ConsoleLogsResourceCommands {
+ get {
+ return ResourceManager.GetString("ConsoleLogsResourceCommands", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Select resource.
///
@@ -140,6 +150,15 @@ public static string ConsoleLogsSelectResourceToolbar {
}
}
+ ///
+ /// Looks up a localized string similar to Console logs settings.
+ ///
+ public static string ConsoleLogsSettings {
+ get {
+ return ResourceManager.GetString("ConsoleLogsSettings", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Unknown state.
///
diff --git a/src/Aspire.Dashboard/Resources/ConsoleLogs.resx b/src/Aspire.Dashboard/Resources/ConsoleLogs.resx
index 8c746b5d741..1ad53e73355 100644
--- a/src/Aspire.Dashboard/Resources/ConsoleLogs.resx
+++ b/src/Aspire.Dashboard/Resources/ConsoleLogs.resx
@@ -1,103 +1,122 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 1.3
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
Console logs
@@ -138,4 +157,10 @@
Download logs
+
+ Console logs settings
+
+
+ Resource commands
+
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.cs.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.cs.xlf
index 0640bef15f6..b2c489b8c32 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.cs.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.cs.xlf
@@ -42,11 +42,21 @@
Protokoly konzoly aplikace {0}
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Vybrat prostředek
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Neznámý stav
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.de.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.de.xlf
index 4f450a8f471..945cfd96baa 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.de.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.de.xlf
@@ -42,11 +42,21 @@
{0} Konsolenprotokolle
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Ressource auswählen
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Unbekannter Status
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.es.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.es.xlf
index 996efb7694f..5ef4c2b8c86 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.es.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.es.xlf
@@ -42,11 +42,21 @@
Registros de consola de {0}
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Seleccionar recurso
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Estado desconocido
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.fr.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.fr.xlf
index 6ba1919534a..1accc736620 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.fr.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.fr.xlf
@@ -42,11 +42,21 @@
Journaux de console {0}
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Sélectionner une ressource
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
État inconnu
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.it.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.it.xlf
index 71fb0c80a4c..026a5c0c564 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.it.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.it.xlf
@@ -42,11 +42,21 @@
{0} log della console
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Seleziona risorsa
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Stato sconosciuto
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ja.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ja.xlf
index ee33f3f91ef..a6c15067fb7 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ja.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ja.xlf
@@ -42,11 +42,21 @@
{0} のコンソール ログ
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
リソースの選択
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
不明な状態
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ko.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ko.xlf
index 1848f047de0..e78dab3621d 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ko.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ko.xlf
@@ -42,11 +42,21 @@
{0} 콘솔 로그
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
리소스 선택
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
알 수 없는 상태
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pl.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pl.xlf
index 4ccf66de19e..198e74edfdf 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pl.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pl.xlf
@@ -42,11 +42,21 @@
Dzienniki konsoli: {0}
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Wybierz zasób
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Nieznany stan
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pt-BR.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pt-BR.xlf
index 8a57064a236..4567330ffe9 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pt-BR.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.pt-BR.xlf
@@ -42,11 +42,21 @@
{0} logs do console
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Selecionar recurso
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Estado desconhecido
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ru.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ru.xlf
index 1cf82678865..cb755066446 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ru.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.ru.xlf
@@ -42,11 +42,21 @@
Журналов консоли: {0}
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Выбрать ресурс
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Неизвестное состояние
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.tr.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.tr.xlf
index 54d01bd5798..b4a51781ae3 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.tr.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.tr.xlf
@@ -42,11 +42,21 @@
{0} konsol günlükleri
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
Kaynak seç
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
Bilinmeyen durum
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hans.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hans.xlf
index 9dd761d71ba..1e12760dd16 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hans.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hans.xlf
@@ -42,11 +42,21 @@
{0} 控制台日志
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
选择资源
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
未知状态
diff --git a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hant.xlf b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hant.xlf
index 6755e57cfa1..bc77913c174 100644
--- a/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hant.xlf
+++ b/src/Aspire.Dashboard/Resources/xlf/ConsoleLogs.zh-Hant.xlf
@@ -42,11 +42,21 @@
{0} 主控台記錄
{0} is an application name
+
+ Resource commands
+ Resource commands
+
+
Select resource
選取資源
+
+ Console logs settings
+ Console logs settings
+
+
Unknown state
未知狀態
diff --git a/src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs b/src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs
index 0c8f1e1c869..c305fc5b426 100644
--- a/src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs
+++ b/src/Aspire.Dashboard/Utils/DashboardUIHelpers.cs
@@ -14,4 +14,7 @@ internal static class DashboardUIHelpers
// If there is no count then default to a limit to avoid getting all data.
// Given the size of rows on dashboard grids, 100 rows should always fill the grid on the screen.
public const int DefaultDataGridResultCount = 100;
+
+ // Don't attempt to display more than 2 highlighted commands. Many commands will take up too much space.
+ public const int MaxHighlightedCommands = 2;
}
diff --git a/src/Aspire.Hosting/ApplicationModel/CommandsConfigurationExtensions.cs b/src/Aspire.Hosting/ApplicationModel/CommandsConfigurationExtensions.cs
index e6e9030383e..9f2e45f1a04 100644
--- a/src/Aspire.Hosting/ApplicationModel/CommandsConfigurationExtensions.cs
+++ b/src/Aspire.Hosting/ApplicationModel/CommandsConfigurationExtensions.cs
@@ -44,7 +44,7 @@ internal static void AddLifeCycleCommands(this IResource resource)
return ResourceCommandState.Hidden;
}
},
- displayDescription: null,
+ displayDescription: "Start resource",
parameter: null,
confirmationMessage: null,
iconName: "Play",
@@ -76,7 +76,7 @@ internal static void AddLifeCycleCommands(this IResource resource)
return ResourceCommandState.Hidden;
}
},
- displayDescription: null,
+ displayDescription: "Stop resource",
parameter: null,
confirmationMessage: null,
iconName: "Stop",
@@ -105,7 +105,7 @@ internal static void AddLifeCycleCommands(this IResource resource)
return ResourceCommandState.Enabled;
}
},
- displayDescription: null,
+ displayDescription: "Restart resource",
parameter: null,
confirmationMessage: null,
iconName: "ArrowCounterclockwise",
diff --git a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs
index 9f84874c6c0..8e3de576f0a 100644
--- a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs
+++ b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs
@@ -162,6 +162,7 @@ private void SetupConsoleLogsServices(TestDashboardClient? dashboardClient = nul
Services.AddSingleton(loggerFactory);
Services.AddSingleton();
Services.AddSingleton();
+ Services.AddSingleton();
Services.AddSingleton>(Options.Create(new DashboardOptions()));
Services.AddSingleton();
Services.AddSingleton();
@@ -171,6 +172,7 @@ private void SetupConsoleLogsServices(TestDashboardClient? dashboardClient = nul
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton(dashboardClient ?? new TestDashboardClient());
+ Services.AddSingleton();
}
private static string GetFluentFile(string filePath, Version version)