From b25cc60e795150867bc603e5f8f6692bf2b67078 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 14 Apr 2025 09:19:16 +0800 Subject: [PATCH 1/2] Add URLs to console logs actions and context menu --- .../Controls/ResourceActions.razor.cs | 3 +- .../Components/Pages/ConsoleLogs.razor.cs | 3 +- .../Components/Pages/Resources.razor.cs | 3 +- .../Model/ResourceMenuItems.cs | 32 ++++++++++++++++++- src/Aspire.Dashboard/wwwroot/js/app.js | 19 ++++++++--- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.cs b/src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.cs index 603b491e8d5..032c526e290 100644 --- a/src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.cs +++ b/src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.cs @@ -73,7 +73,8 @@ protected override void OnParametersSet() OnViewDetails, CommandSelected, IsCommandExecuting, - showConsoleLogsItem: true); + showConsoleLogsItem: true, + showUrls: false); // If display is desktop then we display highlighted commands next to the ... button. if (ViewportInformation.IsDesktop) diff --git a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs index 58e58927138..ff2e44748ad 100644 --- a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs @@ -355,7 +355,8 @@ private void UpdateMenuButtons() }, ExecuteResourceCommandAsync, (resource, command) => DashboardCommandExecutor.IsExecuting(resource.Name, command.Name), - showConsoleLogsItem: false); + showConsoleLogsItem: false, + showUrls: true); } } diff --git a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs index 5d87f0012e8..07c0943dbcd 100644 --- a/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/Resources.razor.cs @@ -531,7 +531,8 @@ private async Task ShowContextMenuAsync(ResourceViewModel resource, int clientX, (buttonId) => ShowResourceDetailsAsync(resource, buttonId), (command) => ExecuteResourceCommandAsync(resource, command), (resource, command) => DashboardCommandExecutor.IsExecuting(resource.Name, command.Name), - showConsoleLogsItem: true); + showConsoleLogsItem: true, + showUrls: true); // The previous context menu should always be closed by this point but complete just in case. _contextMenuClosedTcs?.TrySetResult(); diff --git a/src/Aspire.Dashboard/Model/ResourceMenuItems.cs b/src/Aspire.Dashboard/Model/ResourceMenuItems.cs index 3d8a95f28e6..5b0e2945e0a 100644 --- a/src/Aspire.Dashboard/Model/ResourceMenuItems.cs +++ b/src/Aspire.Dashboard/Model/ResourceMenuItems.cs @@ -17,6 +17,7 @@ public static class ResourceMenuItems private static readonly Icon s_structuredLogsIcon = new Icons.Regular.Size16.SlideTextSparkle(); private static readonly Icon s_tracesIcon = new Icons.Regular.Size16.GanttChart(); private static readonly Icon s_metricsIcon = new Icons.Regular.Size16.ChartMultiple(); + private static readonly Icon s_linkIcon = new Icons.Regular.Size16.Link(); public static void AddMenuItems( List menuItems, @@ -30,7 +31,8 @@ public static void AddMenuItems( Func onViewDetails, Func commandSelected, Func isCommandExecuting, - bool showConsoleLogsItem) + bool showConsoleLogsItem, + bool showUrls) { menuItems.Add(new MenuButtonItem { @@ -115,5 +117,33 @@ public static void AddMenuItems( }); } } + + if (showUrls) + { + var urls = ResourceUrlHelpers.GetUrls(resource, includeInternalUrls: false, includeNonEndpointUrls: true) + .Where(u => !string.IsNullOrEmpty(u.Url)) + .ToList(); + + if (urls.Count > 0) + { + menuItems.Add(new MenuButtonItem { IsDivider = true }); + } + + foreach (var url in urls) + { + menuItems.Add(new MenuButtonItem + { + Text = url.Text, + Tooltip = url.Url, + Icon = s_linkIcon, + AdditionalAttributes = new Dictionary + { + ["data-openbutton"] = "true", + ["data-url"] = url.Url!, + ["data-target"] = "_blank" + } + }); + } + } } } diff --git a/src/Aspire.Dashboard/wwwroot/js/app.js b/src/Aspire.Dashboard/wwwroot/js/app.js index 92e5decabde..755319a70fe 100644 --- a/src/Aspire.Dashboard/wwwroot/js/app.js +++ b/src/Aspire.Dashboard/wwwroot/js/app.js @@ -37,13 +37,17 @@ function getFluentMenuItemForTarget(element) { return null; } -// Register a global click event listener to handle copy button clicks. +// Register a global click event listener to handle copy/open button clicks. // Required because an "onclick" attribute is denied by CSP. document.addEventListener("click", function (e) { // The copy 'button' could either be a button or a menu item. - const targetElement = isElementTagName(e.target, "fluent-button") ? e.target : getFluentMenuItemForTarget(e.target) - if (targetElement && targetElement.getAttribute("data-copybutton")) { - buttonCopyTextToClipboard(targetElement); + const targetElement = isElementTagName(e.target, "fluent-button") ? e.target : getFluentMenuItemForTarget(e.target); + if (targetElement) { + if (targetElement.getAttribute("data-copybutton")) { + buttonCopyTextToClipboard(targetElement); + } else if (targetElement.getAttribute("data-openbutton")) { + buttonOpenLink(targetElement); + } e.stopPropagation(); } }); @@ -114,6 +118,13 @@ function isScrolledToBottom(container) { return difference < marginOfError; } +window.buttonOpenLink = function (element) { + const url = element.getAttribute("data-url"); + const target = element.getAttribute("data-target"); + + window.open(url, target, "noopener,noreferrer"); +} + window.buttonCopyTextToClipboard = function(element) { const text = element.getAttribute("data-text"); const precopy = element.getAttribute("data-precopy"); From fe19487ee96bb425a90381f7f21ccd7406763453 Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Mon, 14 Apr 2025 12:38:13 +0800 Subject: [PATCH 2/2] Update src/Aspire.Dashboard/Model/ResourceMenuItems.cs --- src/Aspire.Dashboard/Model/ResourceMenuItems.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Aspire.Dashboard/Model/ResourceMenuItems.cs b/src/Aspire.Dashboard/Model/ResourceMenuItems.cs index 5b0e2945e0a..0298bf7c649 100644 --- a/src/Aspire.Dashboard/Model/ResourceMenuItems.cs +++ b/src/Aspire.Dashboard/Model/ResourceMenuItems.cs @@ -131,6 +131,8 @@ public static void AddMenuItems( foreach (var url in urls) { + // Opens the URL in a new window when clicked. + // It's important that this is done in the onclick event so the browser popup allows it. menuItems.Add(new MenuButtonItem { Text = url.Text,