Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ protected override void OnParametersSet()
// in the details grid instead of routing it through masking behavior. Preserve the
// display/highlight metadata so the placeholder keeps the original property behavior.
if (_resource.HasMissingParameterValueState() &&
property.KnownProperty?.Key == KnownProperties.Parameter.Value &&
string.Equals(property.Name, KnownProperties.Parameter.Value, StringComparisons.ResourcePropertyName) &&
property.IsValueSensitive)
{
displayedProperty = new ResourcePropertyViewModel(
name: property.Name,
value: property.Value,
isValueSensitive: false,
knownProperty: property.KnownProperty,
priority: property.Priority,
sortOrder: property.SortOrder,
displayName: property.DisplayName,
isHighlighted: property.IsHighlighted);
}
Expand Down Expand Up @@ -227,7 +227,7 @@ protected override void OnParametersSet()
// as the parameters grid so the details panel stays consistent with the grid.
if (_resource.HasMissingParameterValueState())
{
_valueComponents[KnownProperties.Parameter.Value] = new ComponentMetadata
var metadata = new ComponentMetadata
{
Type = typeof(ParameterValueDisplayCell),
Parameters =
Expand All @@ -237,6 +237,9 @@ protected override void OnParametersSet()
["IsCommandExecuting"] = IsCommandExecuting,
}
};

_valueComponents[KnownProperties.Parameter.Value] = metadata;
_valueComponents[DisplayedResourcePropertyViewModel.GetUnknownKey(KnownProperties.Parameter.Value)] = metadata;
}

UpdateResourceActionsMenu();
Expand Down Expand Up @@ -396,7 +399,9 @@ private void AddStateDescriptionProperty(ResourceViewModel resource)
value: Value.ForString(stateDescription),
isValueSensitive: false,
knownProperty: new KnownProperty(StateDescriptionPropertyKey, _ => ControlStringsLoc[nameof(ControlsStrings.ResourceDetailsStateDescriptionHeader)]),
priority: 1),
sortOrder: KnownResourcePropertySortOrder.State,
displayName: null,
isHighlighted: false),
Loc,
TimeProvider));
}
Expand All @@ -410,7 +415,7 @@ private IEnumerable<DisplayedResourcePropertyViewModel> GetResourceProperties(bo
|| string.Equals(vm.KnownProperty?.Key, KnownProperties.Resource.State, StringComparisons.ResourcePropertyName));

return ordered
? vms.OrderBy(vm => vm.Priority).ThenBy(vm => vm.DisplayName)
? vms.OrderBy(vm => vm.SortOrder).ThenBy(vm => vm.DisplayName)
: vms;
}

Expand Down
73 changes: 13 additions & 60 deletions src/Aspire.Dashboard/Model/KnownPropertyLookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,34 @@ namespace Aspire.Dashboard.Model;

public interface IKnownPropertyLookup
{
(int priority, KnownProperty? knownProperty) FindProperty(string resourceType, string uid);
(int SortOrder, KnownProperty? KnownProperty) FindProperty(string uid);
}

public sealed class KnownPropertyLookup : IKnownPropertyLookup
{
private readonly List<KnownProperty> _resourceProperties;
private readonly List<KnownProperty> _projectProperties;
private readonly List<KnownProperty> _executableProperties;
private readonly List<KnownProperty> _containerProperties;
private readonly List<KnownProperty> _parameterProperties;
private readonly List<(KnownProperty Property, int SortOrder)> _resourceProperties;

public KnownPropertyLookup()
{
_resourceProperties =
[
new(KnownProperties.Resource.DisplayName, loc => loc[nameof(ResourcesDetailsDisplayNameProperty)]),
new(KnownProperties.Resource.State, loc => loc[nameof(ResourcesDetailsStateProperty)]),
new(KnownProperties.Resource.HealthState, loc => loc[nameof(ResourcesDetailsHealthStateProperty)]),
new(KnownProperties.Resource.StartTime, loc => loc[nameof(ResourcesDetailsStartTimeProperty)]),
new(KnownProperties.Resource.StopTime, loc => loc[nameof(ResourcesDetailsStopTimeProperty)]),
new(KnownProperties.Resource.ExitCode, loc => loc[nameof(ResourcesDetailsExitCodeProperty)]),
new(KnownProperties.Resource.ConnectionString, loc => loc[nameof(ResourcesDetailsConnectionStringProperty)])
];

_projectProperties =
[
.. _resourceProperties,
new(KnownProperties.Project.Path, loc => loc[nameof(ResourcesDetailsProjectPathProperty)]),
new(KnownProperties.Project.LaunchProfile, loc => loc[nameof(ResourcesDetailsProjectLaunchProfileProperty)]),
new(KnownProperties.Executable.Pid, loc => loc[nameof(ResourcesDetailsExecutableProcessIdProperty)]),
];

_executableProperties =
[
.. _resourceProperties,
new(KnownProperties.Executable.Path, loc => loc[nameof(ResourcesDetailsExecutablePathProperty)]),
new(KnownProperties.Executable.WorkDir, loc => loc[nameof(ResourcesDetailsExecutableWorkingDirectoryProperty)]),
new(KnownProperties.Executable.Args, loc => loc[nameof(ResourcesDetailsExecutableArgumentsProperty)]),
new(KnownProperties.Executable.Pid, loc => loc[nameof(ResourcesDetailsExecutableProcessIdProperty)]),
];

_containerProperties =
[
.. _resourceProperties,
new(KnownProperties.Container.Image, loc => loc[nameof(ResourcesDetailsContainerImageProperty)]),
new(KnownProperties.Container.Id, loc => loc[nameof(ResourcesDetailsContainerIdProperty)]),
new(KnownProperties.Container.Command, loc => loc[nameof(ResourcesDetailsContainerCommandProperty)]),
new(KnownProperties.Container.Args, loc => loc[nameof(ResourcesDetailsContainerArgumentsProperty)]),
new(KnownProperties.Container.Ports, loc => loc[nameof(ResourcesDetailsContainerPortsProperty)]),
new(KnownProperties.Container.Lifetime, loc => loc[nameof(ResourcesDetailsContainerLifetimeProperty)]),
];

_parameterProperties =
[
new(KnownProperties.Parameter.Value, loc => loc[nameof(ResourcesDetailsParameterValueProperty)])
new(new(KnownProperties.Resource.DisplayName, loc => loc[nameof(ResourcesDetailsDisplayNameProperty)]), KnownResourcePropertySortOrder.DisplayName),
new(new(KnownProperties.Resource.State, loc => loc[nameof(ResourcesDetailsStateProperty)]), KnownResourcePropertySortOrder.State),
new(new(KnownProperties.Resource.HealthState, loc => loc[nameof(ResourcesDetailsHealthStateProperty)]), KnownResourcePropertySortOrder.HealthState),
new(new(KnownProperties.Resource.StartTime, loc => loc[nameof(ResourcesDetailsStartTimeProperty)]), KnownResourcePropertySortOrder.StartTime),
new(new(KnownProperties.Resource.StopTime, loc => loc[nameof(ResourcesDetailsStopTimeProperty)]), KnownResourcePropertySortOrder.StopTime),
new(new(KnownProperties.Resource.ExitCode, loc => loc[nameof(ResourcesDetailsExitCodeProperty)]), KnownResourcePropertySortOrder.ExitCode),
new(new(KnownProperties.Resource.ConnectionString, loc => loc[nameof(ResourcesDetailsConnectionStringProperty)]), KnownResourcePropertySortOrder.ConnectionString)
];
}

public (int priority, KnownProperty? knownProperty) FindProperty(string resourceType, string uid)
public (int SortOrder, KnownProperty? KnownProperty) FindProperty(string uid)
{
var knownProperties = resourceType switch
{
KnownResourceTypes.Project => _projectProperties,
KnownResourceTypes.Executable => _executableProperties,
KnownResourceTypes.Container => _containerProperties,
KnownResourceTypes.Parameter => _parameterProperties,
_ => _resourceProperties
};

for (var i = 0; i < knownProperties.Count; i++)
foreach (var property in _resourceProperties)
{
Comment thread
davidfowl marked this conversation as resolved.
var kp = knownProperties[i];
if (kp.Key == uid)
if (property.Property.Key == uid)
{
return (i, kp);
return (property.SortOrder, property.Property);
}
}

Expand Down
46 changes: 46 additions & 0 deletions src/Aspire.Dashboard/Model/LegacyResourcePropertyMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using static Aspire.Dashboard.Resources.Resources;

namespace Aspire.Dashboard.Model;

/// <summary>
/// Provides temporary display metadata for resource-specific properties emitted by older resource servers.
/// </summary>
internal static class LegacyResourcePropertyMetadata
{
/// <summary>
/// Gets legacy metadata for resource-specific properties that predate producer-supplied display metadata.
/// </summary>
internal static (int SortOrder, KnownProperty KnownProperty)? Get(string resourceType, string propertyName)
{
var metadata = (resourceType, propertyName) switch
{
(KnownResourceTypes.Container, KnownProperties.Container.Image) => Create(KnownProperties.Container.Image, nameof(ResourcesDetailsContainerImageProperty), KnownResourcePropertySortOrder.ProducerDefinedStart),
(KnownResourceTypes.Container, KnownProperties.Container.Id) => Create(KnownProperties.Container.Id, nameof(ResourcesDetailsContainerIdProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 1),
(KnownResourceTypes.Container, KnownProperties.Container.Command) => Create(KnownProperties.Container.Command, nameof(ResourcesDetailsContainerCommandProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 2),
(KnownResourceTypes.Container, KnownProperties.Container.Args) => Create(KnownProperties.Container.Args, nameof(ResourcesDetailsContainerArgumentsProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 3),
(KnownResourceTypes.Container, KnownProperties.Container.Ports) => Create(KnownProperties.Container.Ports, nameof(ResourcesDetailsContainerPortsProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 4),
(KnownResourceTypes.Container, KnownProperties.Container.Lifetime) => Create(KnownProperties.Container.Lifetime, nameof(ResourcesDetailsContainerLifetimeProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 5),
(KnownResourceTypes.Executable, KnownProperties.Executable.Path) => Create(KnownProperties.Executable.Path, nameof(ResourcesDetailsExecutablePathProperty), KnownResourcePropertySortOrder.ProducerDefinedStart),
(KnownResourceTypes.Executable, KnownProperties.Executable.WorkDir) => Create(KnownProperties.Executable.WorkDir, nameof(ResourcesDetailsExecutableWorkingDirectoryProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 1),
(KnownResourceTypes.Executable, KnownProperties.Executable.Args) => Create(KnownProperties.Executable.Args, nameof(ResourcesDetailsExecutableArgumentsProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 2),
(KnownResourceTypes.Executable, KnownProperties.Executable.Pid) => Create(KnownProperties.Executable.Pid, nameof(ResourcesDetailsExecutableProcessIdProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 3),
(KnownResourceTypes.Project, KnownProperties.Project.Path) => Create(KnownProperties.Project.Path, nameof(ResourcesDetailsProjectPathProperty), KnownResourcePropertySortOrder.ProducerDefinedStart),
(KnownResourceTypes.Project, KnownProperties.Project.LaunchProfile) => Create(KnownProperties.Project.LaunchProfile, nameof(ResourcesDetailsProjectLaunchProfileProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 1),
(KnownResourceTypes.Project, KnownProperties.Executable.Pid) => Create(KnownProperties.Executable.Pid, nameof(ResourcesDetailsExecutableProcessIdProperty), KnownResourcePropertySortOrder.ProducerDefinedStart + 2),
(KnownResourceTypes.Parameter, KnownProperties.Parameter.Value) => Create(KnownProperties.Parameter.Value, nameof(ResourcesDetailsParameterValueProperty), KnownResourcePropertySortOrder.ProducerDefinedStart),
_ => ((int SortOrder, KnownProperty KnownProperty)?)null
};

return metadata;
}

private static (int SortOrder, KnownProperty KnownProperty) Create(string propertyName, string displayNameResourceName, int sortOrder)
{
// This fallback exists only for dashboards connected to pre-metadata resource servers.
// New resource-specific properties should be emitted with producer metadata instead.
return (sortOrder, new(propertyName, loc => loc[displayNameResourceName]));
}
}
12 changes: 7 additions & 5 deletions src/Aspire.Dashboard/Model/ResourceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ public sealed class DisplayedResourcePropertyViewModel : IPropertyGridItem

public string ToolTip => _tooltip.Value;
public KnownProperty? KnownProperty => _propertyViewModel.KnownProperty;
public int Priority => _propertyViewModel.Priority;
public Value Value => _propertyViewModel.Value;
public bool IsHighlighted => _propertyViewModel.IsHighlighted;
public int SortOrder => _propertyViewModel.SortOrder;
public string DisplayName => _propertyViewModel.DisplayName ?? _propertyViewModel.KnownProperty?.GetDisplayName(_loc) ?? _propertyViewModel.Name;

string IPropertyGridItem.Name => DisplayName;
Expand All @@ -338,7 +338,7 @@ public DisplayedResourcePropertyViewModel(ResourcePropertyViewModel propertyView
_browserTimeProvider = browserTimeProvider;

// Known and unknown properties are displayed together. Avoid any duplicate keys.
_key = propertyViewModel.KnownProperty != null ? propertyViewModel.KnownProperty.Key : $"unknown-{propertyViewModel.Name}";
_key = propertyViewModel.KnownProperty != null ? propertyViewModel.KnownProperty.Key : GetUnknownKey(propertyViewModel.Name);

_tooltip = new(() => propertyViewModel.Value.HasStringValue ? propertyViewModel.Value.StringValue : propertyViewModel.Value.ToString());

Expand Down Expand Up @@ -371,6 +371,8 @@ public DisplayedResourcePropertyViewModel(ResourcePropertyViewModel propertyView
});
}

internal static string GetUnknownKey(string propertyName) => $"unknown-{propertyName}";

public bool MatchesFilter(string filter) =>
_propertyViewModel.Name.Contains(filter, StringComparison.CurrentCultureIgnoreCase) ||
DisplayName.Contains(filter, StringComparison.CurrentCultureIgnoreCase) ||
Expand All @@ -387,9 +389,9 @@ public sealed class ResourcePropertyViewModel
public bool IsValueSensitive { get; }
public bool IsValueMasked { get; set; }
public bool IsHighlighted { get; }
public int Priority { get; }
public int SortOrder { get; }

public ResourcePropertyViewModel(string name, Value value, bool isValueSensitive, KnownProperty? knownProperty, int priority, string? displayName = null, bool isHighlighted = false)
public ResourcePropertyViewModel(string name, Value value, bool isValueSensitive, KnownProperty? knownProperty, int sortOrder, string? displayName, bool isHighlighted)
{
ArgumentException.ThrowIfNullOrWhiteSpace(name);

Expand All @@ -398,8 +400,8 @@ public ResourcePropertyViewModel(string name, Value value, bool isValueSensitive
DisplayName = displayName;
IsValueSensitive = isValueSensitive;
KnownProperty = knownProperty;
Priority = priority;
IsHighlighted = isHighlighted;
SortOrder = sortOrder;
IsValueMasked = isValueSensitive;
}
}
Expand Down
Loading
Loading