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 @@
- +

@Loc[nameof(Dashboard.Resources.ConsoleLogs.ConsoleLogsHeader)]

@@ -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)