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

[Dashboard] [Controls] Show document count beside options list suggestions #146241

Conversation

Heenawter
Copy link
Contributor

@Heenawter Heenawter commented Nov 23, 2022

Closes #145039

Summary

This PR adds a badge beside each options list suggestion that displays how many document that value appears in.

Screen.Recording.2022-12-21.at.4.05.46.PM.mov

Note that, in the above video, clicking "Show only selected" removes the badge regardless of the validity of the selection. As described in #144867 (comment) and the related discussion, it is theoretically possible to still show this badge, thus allowing sorting even when "Show only selected" is on. However, my investigation into this took me on the following journey:

  1. Document count should not be stored as part of the explicitInput, so selections should remain a string array
  2. To get around this, the document count could be stored as part of the validSelections instead, which is part of the component state. That is, validSelections would be an OptionsListSuggestions object rather than a string array
  3. To make (2) happen, we would need to add a secondary API endpoint specifically for translating the explicitInput selections array to the validSelections object

After realizing (3), it became obvious that adding sorting support to "Show only selected" was probably not worth the code complexity that is required - so, at least until we get requests for this feature, I opted to not include it as part of this PR. After all, "Show only selected" is ultimately meant to make it easier to deselect/manage your selections, so showing the document count + allowing sorting in this case doesn't have much of an impact. For the same reasons, searching is also disabled when "Show only selected" is on:

Note
The above screenshots and videos are slightly out-of-date. Refer to #146241 (comment) to see how the design of the document count was changed to reduce visual clutter.

Flaky Test Runner

  • control_group_chaining.ts
  • options_list.ts

Checklist

For maintainers

@Heenawter Heenawter added release_note:enhancement Feature:Dashboard Dashboard related features Feature:Input Control Input controls visualization Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas loe:large Large Level of Effort impact:medium Addressing this issue will have a medium level of impact on the quality/strength of our product. Project:Controls v8.7.0 labels Nov 23, 2022
@Heenawter Heenawter self-assigned this Nov 23, 2022
@Heenawter Heenawter force-pushed the show-document-count-in-options-list_2022-11-23 branch 6 times, most recently from 7a2c1ae to b0436c6 Compare November 24, 2022 21:49
@Heenawter Heenawter force-pushed the show-document-count-in-options-list_2022-11-23 branch 12 times, most recently from 0d429e6 to ea520d0 Compare December 20, 2022 23:45
@Heenawter Heenawter force-pushed the show-document-count-in-options-list_2022-11-23 branch 2 times, most recently from d7cd0ad to 54719f8 Compare December 21, 2022 22:33
const validSelection = findTestSubject(popover, 'optionsList-control-selection-bark');
expect(validSelection.text()).toEqual('bark75');
const title = findTestSubject(popover, 'optionList__ignoredSelectionLabel').text();
expect(title).toEqual('Ignored selection');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because I refactored the optionsListPopoverGetAvailableOptions, it no longer returns "Ignored selection" / "Ignored selections" as part of the selections array. So, I added these unit tests to ensure that we don't lose test coverage for the singular/plural cases of this label 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

This is likely a very good change anyway! Nice cleanup.

Comment on lines +115 to +119
aria-label={
showOnlySelected
? OptionsListStrings.popover.getAllOptionsButtonTitle()
: OptionsListStrings.popover.getSelectedOptionsButtonTitle()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I must have somehow grabbed the wrong aria-label when refactoring the popover to be multiple smaller components - woops! Fixed now :)

Comment on lines -51 to -53
getLoadingMessage: () =>
i18n.translate('controls.optionsList.popover.loading', {
defaultMessage: 'Loading options',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

A bunch of these OptionsListStrings were not being used - they should all be cleaned up now.

Comment on lines 120 to +123
getSortDisabledTooltip: () =>
i18n.translate('controls.optionsList.popover.sortDisabledTooltip', {
defaultMessage: 'Ignore sorting when “Show only selected” is true.',
defaultMessage: 'Sorting is ignored when “Show only selected” is true',
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elastic/kibana-docs Since this tooltip is sticking around as described in the description of this PR, I reworded this to be passive rather than active. To me, the previous wording made it seem like the user could somehow change this behaviour, but they can't - whenever they click "Show only selected", sorting is always ignored!

Dec-21-2022 16-28-01

Interested in your thoughts on this change 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

This change make sense to me.

Comment on lines 124 to 128
getDocumentCountTooltip: (documentCount: number) =>
i18n.translate('controls.optionsList.popover.documentCountTooltip', {
defaultMessage:
'This value appears in {documentCount} {documentCount, plural, one {document} other {documents}}',
values: { documentCount },
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@elastic/kibana-docs This text is for the tooltip that shows up when hovering on the document count:

Dec-21-2022 16-31-27

Let me know if you think this wording is clear 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Text LGTM. Our guideline is to end tooltips with a period. However, none of the tooltip text in this PR does that. For consistency within Lens, we can let it go now and make that change in one global sweep.

@@ -375,11 +386,44 @@ export class DashboardPageControls extends FtrService {
return +(await availableOptions.getAttribute('data-option-count'));
}

public async optionsListPopoverGetAvailableOptions(filterOutExists: boolean = true) {
public async optionsListPopoverGetAvailableOptions() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that the filterOutExists parameter is no longer necessary because the tests that used this were removed as part of removing the "Allow exists" toggle from the UI.

@Heenawter Heenawter marked this pull request as ready for review December 21, 2022 23:54
@Heenawter Heenawter requested a review from a team as a code owner December 21, 2022 23:54
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-presentation (Team:Presentation)

@andreadelrio
Copy link
Contributor

Seems like the count badges are not visible (or are partially displayed) when the values are really long.
image

image

@Heenawter
Copy link
Contributor Author

Heenawter commented Dec 30, 2022

@andreadelrio Oh, good catch!! Fixed in d6033b0

Dec-30-2022 10-06-51

Not that this code should all be cleaned up once we can finally make the transition to using EuiSelectable with the append property for the badge, which is currently blocked until Kibana is bumped to EUI v72.0.0. Once this happens though, the truncation and everything else should be handled for us + a11y would be greatly improved, which would be awesome 👀

@Heenawter
Copy link
Contributor Author

Heenawter commented Jan 3, 2023

Design Update

After feedback from @andreadelrio, we decided that the badge took up a bit too much real estate and added a lot of visual clutter. To clean this up, we opted to move away from using EuiBadge and instead display the document count with some styled EuiText, like so:

image

As part of this, we considered how it would look when the suggestions text was extremely long. However, with the truncation added in d6033b0, it actually still stands out well enough even without a background colour:

image

Copy link
Contributor

@ThomThomson ThomThomson left a comment

Choose a reason for hiding this comment

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

Ran this locally and looked through the code, left a few small nits, but nothing major! LGTM!

direction: 'desc',
};

export const optionsListSortDirections: Readonly<Direction[]> = ['asc', 'desc'] as const;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering why you go through the trouble of creating a new type out of the EUI direction type like this when you could use the EUI type directly or just do a simple union like:

type OptionsListSortDirection = 'asc' | 'desc';

I see what you've done here, and how it works, but I'm not sure I see the benefit?

const validSelection = findTestSubject(popover, 'optionsList-control-selection-bark');
expect(validSelection.text()).toEqual('bark75');
const title = findTestSubject(popover, 'optionList__ignoredSelectionLabel').text();
expect(title).toEqual('Ignored selection');
Copy link
Contributor

Choose a reason for hiding this comment

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

This is likely a very good change anyway! Nice cleanup.

state: WritableDraft<OptionsListReduxState>,
action: PayloadAction<string[]>
) => {
deselectOptions: (state: WritableDraft<OptionsListReduxState>, action: PayloadAction<string>) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why have you changed the payload action type here from string[] to string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Woops! That was probably leftover from playing around with storing the document count as part of the selections array 🙇 It didn't break anything cause it looks like we never actually use deselectOptions, we only ever use deselectOption.... Do you know why this reducer even exists, now that you mention it? 👀

Will change this back to string[] though, regardless

Copy link
Contributor

Choose a reason for hiding this comment

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

Hurm. If it's never used we should probably delete it. It might be a holdover from some earlier development.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call! Will do 👍

@Heenawter
Copy link
Contributor Author

@ThomThomson

I'm wondering why you go through the trouble of creating a new type out of the EUI direction type like this when you could use the EUI type directly or just do a simple union like:

type OptionsListSortDirection = 'asc' | 'desc';

I see what you've done here, and how it works, but I'm not sure I see the benefit?

I did this so I could iterate through the values in .../options_list_popover_sorting_button.tsx like so:

 optionsListSortDirections.map((key) => {
        return {
          id: key,
          iconType: `sort${toSentenceCase(key)}ending`,
          'data-test-subj': `optionsList__sortOrder_${key}`,
          label: OptionsListStrings.editorAndPopover.sortOrder[key].getSortOrderLabel(),
        } as SortOrderItem;
      }),

I don't think I could do something like that if I just used a union type? If there's a way around this, though, I would be totally down 'cause I know the way I did it is a tad bit messy 👀

@ThomThomson
Copy link
Contributor

Ah that makes sense. You can't loop that way through a union type unfortunately, because it doesn't exist at runtime.

I would still argue that since there are only two sort directions, and we don't anticipate ever adding more, that it's overkill to even loop to define the sort buttons. Wouldn't something like this work just as well?

const sortOrderItems: SortOrderItem[] = [
  {
        id: 'asc',
        iconType: `sortAscending`,
        'data-test-subj': `optionsList__sortOrder_asc`,
        label: OptionsListStrings.editorAndPopover.sortOrder.asc.getSortOrderLabel(),
    },
    {
        id: 'desc',
        iconType: `sortDescending`,
        'data-test-subj': `optionsList__sortOrder_desc`,
        label: OptionsListStrings.editorAndPopover.sortOrder.desc.getSortOrderLabel(),
    }
];

The downside being more lines of code, the upside being it doesn't require that typing funkiness, and it's more readable and obvious.

@Heenawter
Copy link
Contributor Author

@ThomThomson Yeah, that's a good call 👍 I agree - cleaner + more readable is probably better than slightly shorter code in this case. Cleaned this up in 5ae9e80

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
controls 455.4KB 456.2KB +793.0B

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
controls 32.8KB 32.8KB -34.0B

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @Heenawter

@Heenawter Heenawter merged commit 37a6636 into elastic:main Jan 3, 2023
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Jan 3, 2023
@Heenawter Heenawter deleted the show-document-count-in-options-list_2022-11-23 branch January 3, 2023 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Dashboard Dashboard related features Feature:Input Control Input controls visualization impact:medium Addressing this issue will have a medium level of impact on the quality/strength of our product. loe:large Large Level of Effort Project:Controls release_note:enhancement Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas v8.7.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Dashboard] [Controls] Show document count for each options list suggestion
7 participants