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

Allow filtering by resource state and health status, and update the filters based on visible grid items #6925

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

adamint
Copy link
Member

@adamint adamint commented Dec 10, 2024

Description

Currently, you can filter resources by type, but it would also be useful to filter by health status or by resource state. I extracted the resource filter UI into its own component ResourceFilters and converted SelectResourceTypes into a component that was more generic and so could be reused for state and health status (SelectResourceOptions). This also meant other refactoring was necessary, such as creating reusable methods Get/SetFieldVisibility from the getter and setter logic previously in AreAllTypesVisible.

Fixes #1190

In a follow-up, we could persist these values in the URL (#3647)

image

(note that, for example, finished and no state have disappeared from available options because no resource with those values is in the grid anymore)
image

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No (largely just a refactor)
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?
Microsoft Reviewers: Open in CodeFlow

{
private async Task OnAllValuesCheckedChangedInternalAsync(bool? newAreAllVisible)
{
AreAllVisible = newAreAllVisible;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously this line (and the logic in OnValueVisibilityChangedInternalAsync) was done in the callback but can be done directly in this component before invoking the callback.

@JamesNK
Copy link
Member

JamesNK commented Dec 11, 2024

What happens if there are a lot of states, resources types and health states? The popup should probably have a maximum height and a scoll bar to handle that situation nicely.

@JamesNK
Copy link
Member

JamesNK commented Dec 11, 2024

Couple of examples of bugs.

Database type isn't in list because its resource is nested. Expanding the parent makes it display:

db-type-not-displayed

Problems with unselecting resource types:

resource-type-not-displayed

These are both caused by filtering available options based on visible resources.

@adamint
Copy link
Member Author

adamint commented Dec 12, 2024

Couple of examples of bugs.

Database type isn't in list because its resource is nested. Expanding the parent makes it display:

Problems with unselecting resource types:

These are both caused by filtering available options based on visible resources.

Reverted the change.

@adamint
Copy link
Member Author

adamint commented Dec 12, 2024

What happens if there are a lot of states, resources types and health states? The popup should probably have a maximum height and a scoll bar to handle that situation nicely.

Added a max height and scroll bar.
image

…lthstatus

# Conflicts:
#	src/Aspire.Dashboard/wwwroot/css/app.css
@adamint adamint requested a review from JamesNK December 12, 2024 18:23
@adamint
Copy link
Member Author

adamint commented Dec 18, 2024

@JamesNK

Comment on lines +18 to +25
if (isVisible)
{
AllValues[value] = true;
}
else
{
AllValues[value] = false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (isVisible)
{
AllValues[value] = true;
}
else
{
AllValues[value] = false;
}
AllValues[value] = isVisible;

Comment on lines +65 to +69
return areAllChecked
? true
: areAllUnchecked
? false
: null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like nested ternary statements. Make at least one of these an if.

Comment on lines +10 to +14
private async Task OnAllValuesCheckedChangedInternalAsync(bool? newAreAllVisible)
{
SetCheckState(newAreAllVisible, AllValues);
await OnAllResourceTypesCheckedChangedAsync();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private async Task OnAllValuesCheckedChangedInternalAsync(bool? newAreAllVisible)
{
SetCheckState(newAreAllVisible, AllValues);
await OnAllResourceTypesCheckedChangedAsync();
}
private async Task OnAllValuesCheckedChangedInternalAsync(bool? newAreAllVisible)
{
SetCheckState(newAreAllVisible, Values);
await OnResourceTypesCheckedChangedAsync();
}

Don't need All in many of these names anymore (I think this suggestion is right). All should just be used when working with the all button now.


@code {
[Parameter, EditorRequired]
public required ConcurrentDictionary<TValue, bool> AllValues { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public required ConcurrentDictionary<TValue, bool> AllValues { get; set; }
public required ConcurrentDictionary<TValue, bool> Values { get; set; }

}
return _resourceTypesToVisibility.TryGetValue(resource.ResourceType, out var typeVisible) && typeVisible
&& _resourceStatesToVisibility.TryGetValue(GetStateOrDefaultText(resource.State, Loc), out var stateVisible) && stateVisible
&& _resourceHealthStatusesToVisibility.TryGetValue(GetStateOrDefaultText(resource.HealthStatus?.Humanize(), Loc), out var healthStateVisible) && healthStateVisible
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&& _resourceHealthStatusesToVisibility.TryGetValue(GetStateOrDefaultText(resource.HealthStatus?.Humanize(), Loc), out var healthStateVisible) && healthStateVisible
&& _resourceHealthStatusesToVisibility.TryGetValue(GetStateOrDefaultText(resource.HealthStatus?.Humanize(), Loc), out var healthStateVisible) && healthStateVisible

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a local method for getting true/false from these dictionaries that avoids the need for TryGetValue.

<FluentButton id="typeFilterButton" slot="end"
Appearance="@(AreAllTypesVisible is true ? Appearance.Stealth : Appearance.Accent)"
<FluentButton id="resourceFilterButton" slot="end"
Appearance="@(AreAllVisibleInAnyFilter ? Appearance.Stealth : Appearance.Accent)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to work anymore.

Comment on lines +39 to +40
Title="@(AreAllVisibleInAnyFilter ? Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFilterAllVisible)] : Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFiltered)])"
aria-label="@(AreAllVisibleInAnyFilter ? Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFilterAllVisible)] : Loc[nameof(Dashboard.Resources.Resources.ResourcesTypeFiltered)])"></FluentButton>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resource text doesn't make sense anymore. It should be made generic to "has filters" vs "no filters"

Comment on lines +170 to +171
_resourceStatesToVisibility.TryAdd(GetStateOrDefaultText(resource.State, Loc), preselectedVisibleResourceStates is null || preselectedVisibleResourceStates.Contains(resource.State ?? string.Empty));
_resourceHealthStatusesToVisibility.TryAdd(GetStateOrDefaultText(resource.HealthStatus?.Humanize(), Loc), preselectedVisibleResourceHealthStates is null || preselectedVisibleResourceHealthStates.Contains(resource.HealthStatus?.Humanize() ?? string.Empty));
Copy link
Member

@JamesNK JamesNK Dec 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no value then the key can be an empty string. It shouldn't be translated text.

Translated text should only be applied in the UI, and this isn't UI related code. Later, when you do show the value in the UI, the view can check if the string is empty and display the default text instead.

@@ -734,3 +734,8 @@ fluent-data-grid-cell.no-ellipsis {
vertical-align: text-bottom;
margin-right: 3px
}

.resources-popup {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.resources-popup {
.resources-filter-popup {


.resources-popup {
max-height: 400px;
overflow-y: scroll;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value always display a scrollbar (disabled when not needed). It should be auto

@dotnet-policy-service dotnet-policy-service bot added the needs-author-action An issue or pull request that requires more info or actions from the author. label Dec 30, 2024
@JamesNK
Copy link
Member

JamesNK commented Dec 30, 2024

I think you should add some component tests to test these changes. We don't tests for resources page yet so you'll need to add some setup code for registering required services and JS calls, but there a lot of other pages already setup that you can follow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-author-action An issue or pull request that requires more info or actions from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Filter resources with errors on dashboard
2 participants