Skip to content

Commit caf5547

Browse files
authored
Add URLs to console logs actions and context menu (#8759)
1 parent dbd0026 commit caf5547

File tree

5 files changed

+54
-8
lines changed

5 files changed

+54
-8
lines changed

src/Aspire.Dashboard/Components/Controls/ResourceActions.razor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ protected override void OnParametersSet()
7373
OnViewDetails,
7474
CommandSelected,
7575
IsCommandExecuting,
76-
showConsoleLogsItem: true);
76+
showConsoleLogsItem: true,
77+
showUrls: false);
7778

7879
// If display is desktop then we display highlighted commands next to the ... button.
7980
if (ViewportInformation.IsDesktop)

src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ private void UpdateMenuButtons()
355355
},
356356
ExecuteResourceCommandAsync,
357357
(resource, command) => DashboardCommandExecutor.IsExecuting(resource.Name, command.Name),
358-
showConsoleLogsItem: false);
358+
showConsoleLogsItem: false,
359+
showUrls: true);
359360
}
360361
}
361362

src/Aspire.Dashboard/Components/Pages/Resources.razor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,8 @@ private async Task ShowContextMenuAsync(ResourceViewModel resource, int clientX,
531531
(buttonId) => ShowResourceDetailsAsync(resource, buttonId),
532532
(command) => ExecuteResourceCommandAsync(resource, command),
533533
(resource, command) => DashboardCommandExecutor.IsExecuting(resource.Name, command.Name),
534-
showConsoleLogsItem: true);
534+
showConsoleLogsItem: true,
535+
showUrls: true);
535536

536537
// The previous context menu should always be closed by this point but complete just in case.
537538
_contextMenuClosedTcs?.TrySetResult();

src/Aspire.Dashboard/Model/ResourceMenuItems.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public static class ResourceMenuItems
1717
private static readonly Icon s_structuredLogsIcon = new Icons.Regular.Size16.SlideTextSparkle();
1818
private static readonly Icon s_tracesIcon = new Icons.Regular.Size16.GanttChart();
1919
private static readonly Icon s_metricsIcon = new Icons.Regular.Size16.ChartMultiple();
20+
private static readonly Icon s_linkIcon = new Icons.Regular.Size16.Link();
2021

2122
public static void AddMenuItems(
2223
List<MenuButtonItem> menuItems,
@@ -30,7 +31,8 @@ public static void AddMenuItems(
3031
Func<string?, Task> onViewDetails,
3132
Func<CommandViewModel, Task> commandSelected,
3233
Func<ResourceViewModel, CommandViewModel, bool> isCommandExecuting,
33-
bool showConsoleLogsItem)
34+
bool showConsoleLogsItem,
35+
bool showUrls)
3436
{
3537
menuItems.Add(new MenuButtonItem
3638
{
@@ -115,5 +117,35 @@ public static void AddMenuItems(
115117
});
116118
}
117119
}
120+
121+
if (showUrls)
122+
{
123+
var urls = ResourceUrlHelpers.GetUrls(resource, includeInternalUrls: false, includeNonEndpointUrls: true)
124+
.Where(u => !string.IsNullOrEmpty(u.Url))
125+
.ToList();
126+
127+
if (urls.Count > 0)
128+
{
129+
menuItems.Add(new MenuButtonItem { IsDivider = true });
130+
}
131+
132+
foreach (var url in urls)
133+
{
134+
// Opens the URL in a new window when clicked.
135+
// It's important that this is done in the onclick event so the browser popup allows it.
136+
menuItems.Add(new MenuButtonItem
137+
{
138+
Text = url.Text,
139+
Tooltip = url.Url,
140+
Icon = s_linkIcon,
141+
AdditionalAttributes = new Dictionary<string, object>
142+
{
143+
["data-openbutton"] = "true",
144+
["data-url"] = url.Url!,
145+
["data-target"] = "_blank"
146+
}
147+
});
148+
}
149+
}
118150
}
119151
}

src/Aspire.Dashboard/wwwroot/js/app.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ function getFluentMenuItemForTarget(element) {
3737
return null;
3838
}
3939

40-
// Register a global click event listener to handle copy button clicks.
40+
// Register a global click event listener to handle copy/open button clicks.
4141
// Required because an "onclick" attribute is denied by CSP.
4242
document.addEventListener("click", function (e) {
4343
// The copy 'button' could either be a button or a menu item.
44-
const targetElement = isElementTagName(e.target, "fluent-button") ? e.target : getFluentMenuItemForTarget(e.target)
45-
if (targetElement && targetElement.getAttribute("data-copybutton")) {
46-
buttonCopyTextToClipboard(targetElement);
44+
const targetElement = isElementTagName(e.target, "fluent-button") ? e.target : getFluentMenuItemForTarget(e.target);
45+
if (targetElement) {
46+
if (targetElement.getAttribute("data-copybutton")) {
47+
buttonCopyTextToClipboard(targetElement);
48+
} else if (targetElement.getAttribute("data-openbutton")) {
49+
buttonOpenLink(targetElement);
50+
}
4751
e.stopPropagation();
4852
}
4953
});
@@ -114,6 +118,13 @@ function isScrolledToBottom(container) {
114118
return difference < marginOfError;
115119
}
116120

121+
window.buttonOpenLink = function (element) {
122+
const url = element.getAttribute("data-url");
123+
const target = element.getAttribute("data-target");
124+
125+
window.open(url, target, "noopener,noreferrer");
126+
}
127+
117128
window.buttonCopyTextToClipboard = function(element) {
118129
const text = element.getAttribute("data-text");
119130
const precopy = element.getAttribute("data-precopy");

0 commit comments

Comments
 (0)