Skip to content
7 changes: 6 additions & 1 deletion src/Aspire.Dashboard/Components/Pages/Resources.razor
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,14 @@
Label="@ControlsStringsLoc[nameof(ControlsStrings.ChartContainerGraphTab)]"
Icon="@(new Icons.Regular.Size24.ShareAndroid())">
</FluentTab>
<FluentTab LabelClass="tab-label"
Id="@($"tab-{ResourceViewKind.Parameters}")"
Label="@Loc[nameof(Dashboard.Resources.Resources.ResourcesParametersTab)]"
Icon="@(new Icons.Regular.Size24.Key())">
</FluentTab>
</FluentTabs>
}
<div class="resources-grid-container" hidden="@(PageViewModel.SelectedViewKind != ResourceViewKind.Table)">
<div class="resources-grid-container" hidden="@(PageViewModel.SelectedViewKind != ResourceViewKind.Table && PageViewModel.SelectedViewKind != ResourceViewKind.Parameters)">
<GridColumnManager @ref="_manager" Columns="@_gridColumns">
<FluentDataGrid @ref="_dataGrid"
ColumnResizeLabels="@_resizeLabels"
Expand Down
115 changes: 113 additions & 2 deletions src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Globalization;
using System.Text;
Expand Down Expand Up @@ -137,6 +138,24 @@ public partial class Resources : ComponentBase, IComponentWithTelemetry, IAsyncD

private bool Filter(ResourceViewModel resource)
{
var isParameter = StringComparers.ResourceType.Equals(resource.ResourceType, KnownResourceTypes.Parameter);

// Parameters tab shows only parameters, Table/Graph tabs show everything except parameters
if (PageViewModel.SelectedViewKind == ResourceViewKind.Parameters)
{
if (!isParameter)
{
return false;
}
}
else
{
if (isParameter)
{
return false;
}
}

return IsKeyValueTrue(resource.ResourceType, PageViewModel.ResourceTypesToVisibility)
&& IsKeyValueTrue(resource.State ?? string.Empty, PageViewModel.ResourceStatesToVisibility)
&& IsKeyValueTrue(resource.HealthStatus?.Humanize() ?? string.Empty, PageViewModel.ResourceHealthStatusesToVisibility)
Expand Down Expand Up @@ -436,7 +455,12 @@ internal IEnumerable<ResourceViewModel> GetFilteredResources()
private ValueTask<GridItemsProviderResult<ResourceGridViewModel>> GetData(GridItemsProviderRequest<ResourceGridViewModel> request)
{
// Get filtered and ordered resources.
var filteredResources = GetFilteredResources()
var filteredResourcesList = GetFilteredResources().ToList();

// Group parameters under a synthetic "Parameters" parent resource
var resourcesWithParametersGrouped = GroupParametersUnderParent(filteredResourcesList);

var filteredResources = resourcesWithParametersGrouped
.Select(r => new ResourceGridViewModel { Resource = r })
.AsQueryable();
filteredResources = request.ApplySorting(filteredResources);
Expand All @@ -460,6 +484,92 @@ private ValueTask<GridItemsProviderResult<ResourceGridViewModel>> GetData(GridIt
return ValueTask.FromResult(GridItemsProviderResult.From(query, orderedResources.Count));
}

private const string ParametersGroupName = "Parameters";

private List<ResourceViewModel> GroupParametersUnderParent(List<ResourceViewModel> resources)
{
var parameters = resources.Where(r => StringComparers.ResourceType.Equals(r.ResourceType, KnownResourceTypes.Parameter)).ToList();

if (parameters.Count == 0)
{
return resources;
}

// Create synthetic "Parameters" parent resource
var parametersParent = new ResourceViewModel
{
Name = ParametersGroupName,
ResourceType = "ParameterGroup",
DisplayName = ParametersGroupName,
Uid = ParametersGroupName,
State = null,
StateStyle = null,
CreationTimeStamp = null,
StartTimeStamp = null,
StopTimeStamp = null,
Environment = ImmutableArray<EnvironmentVariableViewModel>.Empty,
Urls = ImmutableArray<UrlViewModel>.Empty,
Volumes = ImmutableArray<VolumeViewModel>.Empty,
Relationships = ImmutableArray<RelationshipViewModel>.Empty,
Properties = System.Collections.Immutable.ImmutableDictionary<string, ResourcePropertyViewModel>.Empty,
Commands = ImmutableArray<CommandViewModel>.Empty,
HealthReports = ImmutableArray<HealthReportViewModel>.Empty
};

// Set synthetic parent to be collapsed by default
if (!_collapsedResourceNames.Contains(ParametersGroupName))
{
_collapsedResourceNames.Add(ParametersGroupName);
}

// Create new list with parameters having the parent set
var result = new List<ResourceViewModel> { parametersParent };

foreach (var resource in resources)
{
if (StringComparers.ResourceType.Equals(resource.ResourceType, KnownResourceTypes.Parameter))
{
// Update parameter to have Parameters as parent
var parentProperty = new ResourcePropertyViewModel(
KnownProperties.Resource.ParentName,
Google.Protobuf.WellKnownTypes.Value.ForString(ParametersGroupName),
isValueSensitive: false,
knownProperty: null,
priority: 0);

var updatedProperties = resource.Properties.SetItem(KnownProperties.Resource.ParentName, parentProperty);

var updatedParameter = new ResourceViewModel
{
Name = resource.Name,
ResourceType = resource.ResourceType,
DisplayName = resource.DisplayName,
Uid = resource.Uid,
State = resource.State,
StateStyle = resource.StateStyle,
CreationTimeStamp = resource.CreationTimeStamp,
StartTimeStamp = resource.StartTimeStamp,
StopTimeStamp = resource.StopTimeStamp,
Environment = resource.Environment,
Urls = resource.Urls,
Volumes = resource.Volumes,
Relationships = resource.Relationships,
Properties = updatedProperties,
Commands = resource.Commands,
HealthReports = resource.HealthReports
};

result.Add(updatedParameter);
}
else
{
result.Add(resource);
}
}

return result;
}

private void UpdateMenuButtons()
{
_resourcesMenuItems.Clear();
Expand Down Expand Up @@ -876,7 +986,8 @@ public class ResourcesPageState
public enum ResourceViewKind
{
Table,
Graph
Graph,
Parameters
}

public Task UpdateViewModelFromQueryAsync(ResourcesViewModel viewModel)
Expand Down
27 changes: 27 additions & 0 deletions src/Aspire.Dashboard/Resources/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Aspire.Dashboard/Resources/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -309,4 +309,14 @@
<data name="ResourceActionUrlsText" xml:space="preserve">
<value>URLs</value>
</data>
<data name="ParametersPageTitle" xml:space="preserve">
<value>{0} parameters</value>
<comment>{0} is an application name</comment>
</data>
<data name="ParametersHeader" xml:space="preserve">
<value>Parameters</value>
</data>
<data name="ResourcesParametersTab" xml:space="preserve">
<value>Parameters</value>
</data>
</root>
15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/Aspire.Dashboard/Resources/xlf/Resources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading