File: Model\ResourceGraph\ResourceGraphMapper.cs
Web Access
Project: src\src\Aspire.Dashboard\Aspire.Dashboard.csproj (Aspire.Dashboard)
// 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.Immutable;
using System.Xml.Linq;
using Aspire.Dashboard.Otlp.Model;
using Aspire.Dashboard.Resources;
using Microsoft.Extensions.Localization;
using Microsoft.FluentUI.AspNetCore.Components;
using Microsoft.FluentUI.AspNetCore.Components.Extensions;
using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons;
 
namespace Aspire.Dashboard.Model.ResourceGraph;
 
public static class ResourceGraphMapper
{
    private static readonly string s_databaseIcon = GetIconPathData(new Icons.Filled.Size24.Database());
    private static readonly string s_containerIcon = GetIconPathData(new Icons.Filled.Size24.Box());
    private static readonly string s_executableIcon = GetIconPathData(new Icons.Filled.Size24.SettingsCogMultiple());
    private static readonly string s_projectIcon = GetIconPathData(new Icons.Filled.Size24.CodeCircle());
 
    public static ResourceDto MapResource(ResourceViewModel r, IDictionary<string, ResourceViewModel> resourcesByName, IStringLocalizer<Columns> columnsLoc)
    {
        var resolvedNames = new List<string>();
 
        foreach (var resourceRelationships in r.Relationships.GroupBy(r => r.ResourceName, StringComparers.ResourceName))
        {
            var matches = resourcesByName.Values
                .Where(r => string.Equals(r.DisplayName, resourceRelationships.Key, StringComparisons.ResourceName))
                .Where(r => r.KnownState != KnownResourceState.Hidden)
                .ToList();
 
            foreach (var match in matches)
            {
                resolvedNames.Add(match.Name);
            }
        }
 
        var endpoint = ResourceEndpointHelpers.GetEndpoints(r, includeInternalUrls: false).FirstOrDefault();
        var resolvedEndpointText = ResolvedEndpointText(endpoint);
        var resourceName = ResourceViewModel.GetResourceName(r, resourcesByName);
        var color = ColorGenerator.Instance.GetColorHexByKey(resourceName);
 
        var icon = r.ResourceType switch
        {
            KnownResourceTypes.Executable => s_executableIcon,
            KnownResourceTypes.Project => s_projectIcon,
            KnownResourceTypes.Container => s_containerIcon,
            string t => t.Contains("database", StringComparison.OrdinalIgnoreCase) ? s_databaseIcon : s_executableIcon
        };
 
        var stateIcon = ResourceStateViewModel.GetStateViewModel(r, columnsLoc);
 
        var dto = new ResourceDto
        {
            Name = r.Name,
            ResourceType = r.ResourceType,
            DisplayName = ResourceViewModel.GetResourceName(r, resourcesByName),
            Uid = r.Uid,
            ResourceIcon = new IconDto
            {
                Path = icon,
                Color = color,
                Tooltip = r.ResourceType
            },
            StateIcon = new IconDto
            {
                Path = GetIconPathData(stateIcon.Icon),
                Color = stateIcon.Color.ToAttributeValue()!,
                Tooltip = stateIcon.Text ?? r.State
            },
            ReferencedNames = resolvedNames.Distinct().OrderBy(n => n).ToImmutableArray(),
            EndpointUrl = endpoint?.Url,
            EndpointText = resolvedEndpointText
        };
 
        return dto;
    }
 
    private static string ResolvedEndpointText(DisplayedEndpoint? endpoint)
    {
        var text = endpoint?.Text ?? endpoint?.Url;
        if (string.IsNullOrEmpty(text))
        {
            return "No endpoints";
        }
 
        if (Uri.TryCreate(text, UriKind.Absolute, out var uri))
        {
            return $"{uri.Host}:{uri.Port}";
        }
 
        return text;
    }
 
    private static string GetIconPathData(Icon icon)
    {
        var p = icon.Content;
        var e = XElement.Parse(p);
        return e.Attribute("d")!.Value;
    }
}