Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

View details with row click #5000

Merged
merged 4 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 17 additions & 13 deletions src/Aspire.Dashboard/Components/Controls/GridValue.razor
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
}
@if (EnableMasking)
{
<FluentButton Appearance="Appearance.Lightweight"
IconEnd="@(IsMasked ? _unmaskIcon : _maskIcon)"
Title="@(IsMasked ? Loc[nameof(ControlsStrings.GridValueMaskShowValue)] : Loc[nameof(ControlsStrings.GridValueMaskHideValue)])"
OnClick="ToggleMaskStateAsync"
aria-label="@(IsMasked ? Loc[nameof(ControlsStrings.GridValueMaskShowValue)] : Loc[nameof(ControlsStrings.GridValueMaskHideValue)])" />
<div @onclick:stopPropagation="true">
<FluentButton Appearance="Appearance.Lightweight"
IconEnd="@(IsMasked ? _unmaskIcon : _maskIcon)"
Title="@(IsMasked ? Loc[nameof(ControlsStrings.GridValueMaskShowValue)] : Loc[nameof(ControlsStrings.GridValueMaskHideValue)])"
OnClick="ToggleMaskStateAsync"
aria-label="@(IsMasked ? Loc[nameof(ControlsStrings.GridValueMaskShowValue)] : Loc[nameof(ControlsStrings.GridValueMaskHideValue)])" />
</div>
}

@{
Expand All @@ -42,13 +44,15 @@
];
}

<FluentButton Appearance="Appearance.Lightweight"
Id="@_anchorId"
Class="defaultHidden"
Style="float: right; flex-shrink: 0"
AdditionalAttributes="@FluentUIExtensions.GetClipboardCopyAdditionalAttributes(ValueToCopy ?? Value, PreCopyToolTip, PostCopyToolTip, uncapturedAttributes)">
<FluentIcon Class="copy-icon" Style="display:inline;" Icon="Icons.Regular.Size16.Copy" />
<FluentIcon Class="checkmark-icon" Style="display:none;" Icon="Icons.Regular.Size16.Checkmark" />
</FluentButton>
<div @onclick:stopPropagation="true">
<FluentButton Appearance="Appearance.Lightweight"
Id="@_anchorId"
Class="defaultHidden"
Style="float: right; flex-shrink: 0"
AdditionalAttributes="@FluentUIExtensions.GetClipboardCopyAdditionalAttributes(ValueToCopy ?? Value, PreCopyToolTip, PostCopyToolTip, uncapturedAttributes)">
<FluentIcon Class="copy-icon" Style="display:inline;" Icon="Icons.Regular.Size16.Copy" />
<FluentIcon Class="checkmark-icon" Style="display:none;" Icon="Icons.Regular.Size16.Checkmark" />
</FluentButton>
</div>
<FluentTooltip @ref="_tooltipComponent" Anchor="@_anchorId" Position="TooltipPosition.Top" HideTooltipOnCursorLeave="true">@PreCopyToolTip</FluentTooltip>
</div>
83 changes: 48 additions & 35 deletions src/Aspire.Dashboard/Components/Pages/Resources.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@page "/"
@using Aspire.Dashboard.Components.ResourcesGridColumns
@using Aspire.Dashboard.Model
@using Aspire.Dashboard.Resources
@using Aspire.Dashboard.Utils
@using System.Globalization
Expand Down Expand Up @@ -28,19 +29,18 @@
IconEnd="@(new Icons.Regular.Size24.Filter())"
@onclick="() => _isTypeFilterVisible = !_isTypeFilterVisible"
Title="@(AreAllTypesVisible is true ? Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFilterAllVisible)] : Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFiltered)])"
aria-label="@(AreAllTypesVisible is true ? Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFilterAllVisible)] : Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFiltered)])"/>
aria-label="@(AreAllTypesVisible is true ? Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFilterAllVisible)] : Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFiltered)])" />
}
else
{
<div>
<h5>@Loc[nameof(Dashboard.Resources.Resources.ResourcesResourceTypesHeader)]</h5>

<SelectResourceTypes
AllResourceTypes="_allResourceTypes"
VisibleResourceTypes="_visibleResourceTypes"
OnAllResourceTypesCheckedChanged="@(b => AreAllTypesVisible = b)"
AreAllTypesVisible="@(() => AreAllTypesVisible)"
OnResourceTypeVisibilityChangedAsync="@OnResourceTypeVisibilityChangedAsync" />
<SelectResourceTypes AllResourceTypes="_allResourceTypes"
VisibleResourceTypes="_visibleResourceTypes"
OnAllResourceTypesCheckedChanged="@(b => AreAllTypesVisible = b)"
AreAllTypesVisible="@(() => AreAllTypesVisible)"
OnResourceTypeVisibilityChangedAsync="@OnResourceTypeVisibilityChangedAsync" />
</div>
}

Expand All @@ -49,19 +49,18 @@
@bind-Value="_filter"
slot="end"
Label="@(ViewportInformation.IsDesktop ? null : ControlsStringsLoc[nameof(ControlsStrings.FilterPlaceholder)].Value)"
@bind-Value:after="HandleSearchFilterChangedAsync"/>
@bind-Value:after="HandleSearchFilterChangedAsync" />
</ToolbarSection>

<MainSection>
<FluentPopover AnchorId="typeFilterButton" @bind-Open="_isTypeFilterVisible" AutoFocus="true">
<Header>@Loc[nameof(Dashboard.Resources.Resources.ResourcesResourceTypesHeader)]</Header>
<Body>
<SelectResourceTypes
AllResourceTypes="_allResourceTypes"
VisibleResourceTypes="_visibleResourceTypes"
OnAllResourceTypesCheckedChanged="@(b => AreAllTypesVisible = b)"
AreAllTypesVisible="@(() => AreAllTypesVisible)"
OnResourceTypeVisibilityChangedAsync="@OnResourceTypeVisibilityChangedAsync" />
<SelectResourceTypes AllResourceTypes="_allResourceTypes"
VisibleResourceTypes="_visibleResourceTypes"
OnAllResourceTypesCheckedChanged="@(b => AreAllTypesVisible = b)"
AreAllTypesVisible="@(() => AreAllTypesVisible)"
OnResourceTypeVisibilityChangedAsync="@OnResourceTypeVisibilityChangedAsync" />
</Body>
</FluentPopover>

Expand All @@ -72,51 +71,65 @@
ViewKey="ResourcesList">
<Summary>
@{
var gridTemplateColumns = HasResourcesWithCommands ? "1fr 1.5fr 1.25fr 1.5fr 2.5fr 2.5fr 1fr 1fr 1fr" : "1fr 1.5fr 1.25fr 1.5fr 2.5fr 2.5fr 1fr 1fr";
var gridTemplateColumns = HasResourcesWithCommands ? "1fr 1.5fr 1.25fr 1.5fr 2.5fr 2.5fr 1fr 1fr 1fr" : "1fr 1.5fr 1.25fr 1.5fr 2.5fr 2.5fr 1fr 1fr";
}
<FluentDataGrid Virtualize="true" GenerateHeader="GenerateHeaderOption.Sticky" ItemSize="46" Items="@FilteredResources" ResizableColumns="true" GridTemplateColumns="@gridTemplateColumns" RowClass="GetRowClass" Loading="_isLoading" ShowHover="true">
<FluentDataGrid Virtualize="true"
GenerateHeader="GenerateHeaderOption.Sticky"
ItemSize="46"
Items="@FilteredResources"
ResizableColumns="true"
GridTemplateColumns="@gridTemplateColumns"
RowClass="GetRowClass"
Loading="_isLoading"
ShowHover="true"
TGridItem="ResourceViewModel"
OnRowClick="@(r => r.ExecuteOnDefault(d => ShowResourceDetailsAsync(d, buttonId: null)))"
Class="enable-row-click">
<ChildContent>
<PropertyColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeColumnHeader)]" Property="@(c => c.ResourceType)" Sortable="true" Tooltip="true" TooltipText="@(c => c.ResourceType)"/>
<TemplateColumn Title="@ControlsStringsLoc[nameof(ControlsStrings.NameColumnHeader)]" Sortable="true" SortBy="@_nameSort" Tooltip="true" TooltipText="@(c => GetResourceName(c))" >
<PropertyColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeColumnHeader)]" Property="@(c => c.ResourceType)" Sortable="true" Tooltip="true" TooltipText="@(c => c.ResourceType)" />
<TemplateColumn Title="@ControlsStringsLoc[nameof(ControlsStrings.NameColumnHeader)]" Sortable="true" SortBy="@_nameSort" Tooltip="true" TooltipText="@(c => GetResourceName(c))">
<ResourceNameDisplay Resource="context" FilterText="@_filter" FormatName="GetResourceName" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesStateColumnHeader)]" Sortable="true" SortBy="@_stateSort" Tooltip="true" TooltipText="@(c => c.State.Humanize())">
<StateColumnDisplay Resource="@context" UnviewedErrorCounts ="@_applicationUnviewedErrorCounts" />
<StateColumnDisplay Resource="@context" UnviewedErrorCounts="@_applicationUnviewedErrorCounts" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesStartTimeColumnHeader)]" Sortable="true" SortBy="@_startTimeSort" TooltipText="@(context => context.CreationTimeStamp != null ? FormatHelpers.FormatDateTime(TimeProvider, context.CreationTimeStamp.Value, MillisecondsDisplay.None, CultureInfo.CurrentCulture) : null)" Tooltip="true">
<StartTimeColumnDisplay Resource="@context" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesSourceColumnHeader)]" Tooltip="true" TooltipText="@(ctx => GetSourceColumnValueAndTooltip(ctx)?.Tooltip)">
@if (GetSourceColumnValueAndTooltip(context) is { } columnDisplay)
{
<SourceColumnDisplay Resource="context" FilterText="@_filter" Value="@columnDisplay.Value" ContentAfterValue="@columnDisplay.ContentAfterValue" ValueToCopy="@columnDisplay.ValueToCopy" Tooltip="@columnDisplay.Tooltip" />
<SourceColumnDisplay Resource="context" FilterText="@_filter" Value="@columnDisplay.Value" ContentAfterValue="@columnDisplay.ContentAfterValue" ValueToCopy="@columnDisplay.ValueToCopy" Tooltip="@columnDisplay.Tooltip" />
}
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesEndpointsColumnHeader)]" Tooltip="true" TooltipText="@(ctx => GetEndpointsTooltip(ctx))">
<EndpointsColumnDisplay
Resource="context"
HasMultipleReplicas="HasMultipleReplicas(context)"
DisplayedEndpoints="@GetDisplayedEndpoints(context, out var additionalMessage)"
AdditionalMessage="@additionalMessage" />
<EndpointsColumnDisplay Resource="context"
HasMultipleReplicas="HasMultipleReplicas(context)"
DisplayedEndpoints="@GetDisplayedEndpoints(context, out var additionalMessage)"
AdditionalMessage="@additionalMessage" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesLogsColumnHeader)]" Class="no-ellipsis">
<FluentAnchor Appearance="Appearance.Lightweight" Href="@DashboardUrls.ConsoleLogsUrl(resource: context.Name)">@ControlsStringsLoc[ControlsStrings.ViewAction]</FluentAnchor>
<FluentAnchor Appearance="Appearance.Lightweight" Href="@DashboardUrls.ConsoleLogsUrl(resource: context.Name)" @onclick:stopPropagation="true">@ControlsStringsLoc[ControlsStrings.ViewAction]</FluentAnchor>
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesDetailsColumnHeader)]" Sortable="false" Class="no-ellipsis">
@{
var id = $"details-button-{context.Uid}";
var id = $"details-button-{context.Uid}";
}
<FluentButton Appearance="Appearance.Lightweight"
Id="@id"
Title="@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]"
OnClick="@(() => ShowResourceDetailsAsync(context, id))">@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
<div @onclick:stopPropagation="true">
<FluentButton Appearance="Appearance.Lightweight"
Id="@id"
Title="@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]"
OnClick="@(() => ShowResourceDetailsAsync(context, id))">@ControlsStringsLoc[nameof(ControlsStrings.ViewAction)]</FluentButton>
</div>
</TemplateColumn>
@if (HasResourcesWithCommands)
{
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesCommandsColumnHeader)]">
<ResourceCommands Commands="@context.Commands"
CommandSelected="async (command) => await ExecuteResourceCommandAsync(context, command)" />
</TemplateColumn>
<TemplateColumn Title="@Loc[nameof(Dashboard.Resources.Resources.ResourcesCommandsColumnHeader)]">
<div @onclick:stopPropagation="true">
<ResourceCommands Commands="@context.Commands"
CommandSelected="async (command) => await ExecuteResourceCommandAsync(context, command)" />
</div>
</TemplateColumn>
}
</ChildContent>
<EmptyContent>
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Dashboard/Components/Pages/Resources.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ private bool ApplicationErrorCountsChanged(Dictionary<OtlpApplication, int> newA
return false;
}

private async Task ShowResourceDetailsAsync(ResourceViewModel resource, string buttonId)
private async Task ShowResourceDetailsAsync(ResourceViewModel resource, string? buttonId)
{
_elementIdBeforeDetailsViewOpened = buttonId;

Expand Down
Loading