Skip to content

Commit

Permalink
Add references to UI
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed Aug 19, 2024
1 parent c92e75d commit 8248dae
Show file tree
Hide file tree
Showing 22 changed files with 843 additions and 233 deletions.
44 changes: 36 additions & 8 deletions src/Aspire.Dashboard/Components/Controls/ResourceDetails.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@using Aspire.Dashboard.Components.Controls.Grid
@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Otlp.Model
@using Aspire.Dashboard.Resources
@using Aspire.Dashboard.Utils
@inject IStringLocalizer<ControlsStrings> ControlStringsLoc
Expand Down Expand Up @@ -102,26 +103,53 @@
</AspireTemplateColumn>
</FluentDataGrid>
</FluentAccordionItem>
<FluentAccordionItem Heading="@Loc[nameof(ControlsStrings.SpanDetailsBacklinksHeader)]" Expanded="true">
<FluentAccordionItem Heading="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsReferences)]" Expanded="true">
<div slot="end">
<FluentBadge Appearance="Appearance.Neutral" Circular="true">
@FilteredRelationships.Count()
</FluentBadge>
</div>
<FluentDataGrid TGridItem="RelationshipViewModel"
<FluentDataGrid TGridItem="ResourceDetailRelationship"
Items="@FilteredRelationships"
Style="width:100%"
GenerateHeader="GenerateHeaderOption.Sticky"
GridTemplateColumns="2fr 1.5fr 1fr"
GridTemplateColumns="1fr 0.75fr 0.75fr"
ShowHover="true">
<TemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsSpanColumnHeader)]">
@context.ResourceName
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsResourceHeader)]">
<span style="padding-left:5px; border-left-width: 5px; border-left-style: solid; border-left-color: @(ColorGenerator.Instance.GetColorHexByKey(context.ResourceName));">
@context.ResourceName
</span>
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsSpanColumnHeader)]">
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsTypeHeader)]">
@context.Type
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(ControlsStrings.SpanDetailsDetailsColumnHeader)]">
<FluentButton Appearance="Appearance.Lightweight" OnClick="@(() => OnViewDetailsAsync(context))">@Loc[nameof(ControlsStrings.ViewAction)]</FluentButton>
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]">
<FluentButton Appearance="Appearance.Lightweight" OnClick="@(() => OnViewRelationshipAsync(context))">@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
</TemplateColumn>
</FluentDataGrid>
</FluentAccordionItem>
<FluentAccordionItem Heading="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsBackReferences)]" Expanded="true">
<div slot="end">
<FluentBadge Appearance="Appearance.Neutral" Circular="true">
@FilteredBackRelationships.Count()
</FluentBadge>
</div>
<FluentDataGrid TGridItem="ResourceDetailRelationship"
Items="@FilteredBackRelationships"
Style="width:100%"
GenerateHeader="GenerateHeaderOption.Sticky"
GridTemplateColumns="1fr 0.75fr 0.75fr"
ShowHover="true">
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsResourceHeader)]">
<span style="padding-left:5px; border-left-width: 5px; border-left-style: solid; border-left-color: @(ColorGenerator.Instance.GetColorHexByKey(context.ResourceName));">
@context.ResourceName
</span>
</TemplateColumn>
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsTypeHeader)]">
@context.Type
</TemplateColumn>
<TemplateColumn Title="@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]">
<FluentButton Appearance="Appearance.Lightweight" OnClick="@(() => OnViewRelationshipAsync(context))">@ControlStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
</TemplateColumn>
</FluentDataGrid>
</FluentAccordionItem>
Expand Down
102 changes: 83 additions & 19 deletions src/Aspire.Dashboard/Components/Controls/ResourceDetails.razor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Globalization;
using Aspire.Dashboard.Extensions;
using Aspire.Dashboard.Model;
using Aspire.Dashboard.Utils;
using Google.Protobuf.WellKnownTypes;
Expand All @@ -16,6 +18,9 @@ public partial class ResourceDetails
[Parameter, EditorRequired]
public required ResourceViewModel Resource { get; set; }

[Parameter]
public required ConcurrentDictionary<string, ResourceViewModel> ResourceByName { get; set; }

[Parameter]
public bool ShowSpecOnlyToggle { get; set; }

Expand All @@ -28,6 +33,9 @@ public partial class ResourceDetails
[Inject]
public required BrowserTimeProvider TimeProvider { get; init; }

[Inject]
public required NavigationManager NavigationManager { get; init; }

private bool IsSpecOnlyToggleDisabled => !Resource.Environment.All(i => !i.FromSpec) && !GetResourceValues().Any(v => v.KnownProperty == null);

private bool _showAll;
Expand All @@ -44,8 +52,12 @@ public partial class ResourceDetails
.Where(v => v.Name.Contains(_filter, StringComparison.CurrentCultureIgnoreCase) || v.Text.Contains(_filter, StringComparison.CurrentCultureIgnoreCase) == true)
.AsQueryable();

private IQueryable<RelationshipViewModel> FilteredRelationships => GetRelationships()
.Where(v => v.ResourceName.Contains(_filter, StringComparison.CurrentCultureIgnoreCase) || v.Type.Contains(_filter, StringComparison.CurrentCultureIgnoreCase))
private IQueryable<ResourceDetailRelationship> FilteredRelationships => GetRelationships()
.Where(v => v.Resource.DisplayName.Contains(_filter, StringComparison.CurrentCultureIgnoreCase) || v.Type.Contains(_filter, StringComparison.CurrentCultureIgnoreCase))
.AsQueryable();

private IQueryable<ResourceDetailRelationship> FilteredBackRelationships => GetBackRelationships()
.Where(v => v.Resource.DisplayName.Contains(_filter, StringComparison.CurrentCultureIgnoreCase) || v.Type.Contains(_filter, StringComparison.CurrentCultureIgnoreCase))
.AsQueryable();

private IQueryable<SummaryValue> FilteredResourceValues => GetResourceValues()
Expand Down Expand Up @@ -116,9 +128,66 @@ private void ResetResourceEnvironmentVariableMasks()
}
}

private IEnumerable<RelationshipViewModel> GetRelationships()
private IEnumerable<ResourceDetailRelationship> GetRelationships()
{
if (ResourceByName == null)
{
return [];
}

var items = new List<ResourceDetailRelationship>();

foreach (var relationship in Resource.Relationships)
{
var matches = ResourceByName.Values
.Where(r => string.Equals(r.DisplayName, relationship.ResourceName, StringComparisons.ResourceName))
.Where(r => !r.IsHiddenState())
.ToList();

foreach (var match in matches)
{
items.Add(new()
{
Resource = match,
ResourceName = ResourceViewModel.GetResourceName(match, ResourceByName),
Type = relationship.Type
});
}
}

return items;
}

private IEnumerable<ResourceDetailRelationship> GetBackRelationships()
{
return Resource.Relationships;
if (ResourceByName == null)
{
return [];
}

var items = new List<ResourceDetailRelationship>();

var otherResources = ResourceByName.Values
.Where(r => r != Resource)
.Where(r => !r.IsHiddenState());

foreach (var otherResource in otherResources)
{
foreach (var relationship in otherResource.Relationships)
{
if (string.Equals(relationship.ResourceName, Resource.DisplayName, StringComparisons.ResourceName))
{
items.Add(new()
{
Resource = otherResource,
ResourceName = ResourceViewModel.GetResourceName(otherResource, ResourceByName),
Type = relationship.Type
});
}
}
}

return items.OrderBy(r => r.ResourceName);
}

private IEnumerable<DisplayedEndpoint> GetEndpoints()
Expand Down Expand Up @@ -224,22 +293,10 @@ private void CheckAllMaskStates()
};
}

public async Task OnViewDetailsAsync(RelationshipViewModel vm)
public Task OnViewRelationshipAsync(ResourceDetailRelationship relationship)
{
await Task.Yield();
//var available = await MetricsHelpers.WaitForSpanToBeAvailableAsync(
// traceId: vm.TraceId,
// spanId: vm.SpanId,
// getSpan: TelemetryRepository.GetSpan,
// DialogService,
// InvokeAsync,
// DialogsLoc,
// _cts.Token).ConfigureAwait(false);

//if (available)
//{
// NavigationManager.NavigateTo(DashboardUrls.TraceDetailUrl(vm.TraceId, spanId: vm.SpanId));
//}
NavigationManager.NavigateTo(DashboardUrls.ResourcesUrl(resource: relationship.Resource.Name));
return Task.CompletedTask;
}

private sealed class SummaryValue
Expand All @@ -252,3 +309,10 @@ private sealed class SummaryValue

private sealed record KnownProperty(string Key, string DisplayName);
}

public sealed class ResourceDetailRelationship
{
public required ResourceViewModel Resource { get; init; }
public required string ResourceName { get; init; }
public required string Type { get; set; }
}
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/Resources.razor
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
</FluentDataGrid>
</Summary>
<Details>
<ResourceDetails Resource="context" ShowSpecOnlyToggle="true" />
<ResourceDetails Resource="context" ResourceByName="_resourceByName" ShowSpecOnlyToggle="true" />
</Details>
</SummaryDetailsView>
</MainSection>
Expand Down
18 changes: 18 additions & 0 deletions src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public partial class Resources : ComponentBase, IAsyncDisposable
[SupplyParameterFromQuery]
public string? VisibleTypes { get; set; }

[Parameter]
[SupplyParameterFromQuery(Name = "resource")]
public string? ResourceName { get; set; }

private ResourceViewModel? SelectedResource { get; set; }

private readonly CancellationTokenSource _watchTaskCancellationTokenSource = new();
Expand Down Expand Up @@ -205,6 +209,20 @@ async Task SubscribeResourcesAsync()
}
}

protected override async Task OnParametersSetAsync()
{
if (ResourceName is not null)
{
if (_resourceByName.TryGetValue(ResourceName, out var selectedResource))
{
await ShowResourceDetailsAsync(selectedResource, buttonId: null);
}

// Navigate to remove ?resource=xxx in the URL.
NavigationManager.NavigateTo(DashboardUrls.ResourcesUrl(), new NavigationOptions { ReplaceHistoryEntry = true });
}
}

private bool ApplicationErrorCountsChanged(Dictionary<OtlpApplication, int> newApplicationUnviewedErrorCounts)
{
if (_applicationUnviewedErrorCounts == null || _applicationUnviewedErrorCounts.Count != newApplicationUnviewedErrorCounts.Count)
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/TraceDetail.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public partial class TraceDetail : ComponentBase

[Parameter]
[SupplyParameterFromQuery]
public required string? SpanId { get; set; }
public string? SpanId { get; set; }

[Inject]
public required TelemetryRepository TelemetryRepository { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
@using Aspire.Dashboard.Resources
@inject IStringLocalizer<Columns> Loc

<span title="@FormatName(Resource)"><FluentHighlighter HighlightedText="@FilterText" Text="@FormatName(Resource)"/></span>
<span style="padding-left:5px; border-left-width: 5px; border-left-style: solid; border-left-color: @(ColorGenerator.Instance.GetColorHexByKey(FormatName(Resource)));">
<span title="@FormatName(Resource)"><FluentHighlighter HighlightedText="@FilterText" Text="@FormatName(Resource)"/></span>
</span>

@code {
[Parameter, EditorRequired]
Expand Down
Loading

0 comments on commit 8248dae

Please sign in to comment.