-
Notifications
You must be signed in to change notification settings - Fork 14k
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
feat: Select all for synchronous select #22084
feat: Select all for synchronous select #22084
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @cccs-RyanK. I left some first-pass comments.
…elect-all-synchronous-select
…elect-all-synchronous-select
@@ -94,7 +94,7 @@ test('table should be visible when expanded is true', async () => { | |||
expect(dbSelect).toBeInTheDocument(); | |||
expect(schemaSelect).toBeInTheDocument(); | |||
expect(dropdown).toBeInTheDocument(); | |||
expect(abUser).toHaveLength(2); | |||
expect(abUser).toHaveLength(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test adds one item into a 'multi' select component and then selects it. With the new behaviour, that counts as selecting all which renders a custom tag with the total number of items selected. This test would fail because it expected the single tag to be rendered in the select component when that is no longer the expected behaviour, so I changed the test.
Another option is to make it so that the select all functionality is disabled in the case where there is only one item in the options. Please let me know your thoughts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I like the idea of disabling the "select all" when only 1 option is available.
Codecov Report
@@ Coverage Diff @@
## master #22084 +/- ##
==========================================
- Coverage 67.09% 66.99% -0.10%
==========================================
Files 1869 1876 +7
Lines 71597 71814 +217
Branches 7821 7879 +58
==========================================
+ Hits 48035 48110 +75
- Misses 21534 21675 +141
- Partials 2028 2029 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
/testenv up |
@kgabryje Ephemeral environment spinning up at http://34.217.113.86:8080. Credentials are |
Hi @cccs-RyanK. Thank you for this PR! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the first-pass review comments @cccs-RyanK. Here are the second review comments:
When "Select all" is checked, we shouldn't show the +N tag.
We're showing "Select All (12)" but there are 11 items. We shouldn't count the "Select All" option:
useEffect(() => { | ||
setSelectValue(value); | ||
// if all values are selected, add select all to value | ||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're missing fullSelectOptions.length, isSingleMode, labelInValue
in the dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added isSingleMode and labelInValue as dependencies, but i purposefully left out fullSelectOptions.length because this hook should only be called when the component props have been changed. fullSelectOptions can change when new options are added and in that case we don't want the select value to be reset (erasing the newly added options).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. This is indicative that the effect should be broken into two unrelated operations. Like this:
useEffect(() => {
setSelectValue(value);
}, [value]);
useEffect(() => {
// if all values are selected, add select all to value
if (
!isSingleMode &&
ensureIsArray(value).length === fullSelectOptions.length &&
fullSelectOptions.length > 0
) {
setSelectValue(
labelInValue
? ([...ensureIsArray(value), selectAllOption] as AntdLabeledValue[])
: ([
...ensureIsArray(value),
SELECT_ALL_VALUE,
] as AntdLabeledValue[]),
);
}
}, [value, isSingleMode, labelInValue, fullSelectOptions.length]);
When Screen.Recording.2022-12-12.at.12.13.43.PM.mov |
When fixing the reported issues, can you please add the following test cases?
|
FYI @cccs-RyanK @EugeneTorap this is on my priority todo list, and I'm hoping to give it a proper review+test pass this weekend. |
@cccs-RyanK @geido I think we should disassociate the uncheck and remove actions on new items. We could have an X icon to remove new items. I can think of a scenario where a user is adding filters to a chart and after seeing the results, the user can check/uncheck the added filters to test different combinations. Making the remove action more intentional will improve UX. Let's tackle this in a separate PR. For now, I'm fine with removing all items when Select All is unchecked. |
When working in Screen.Recording.2023-01-11.at.11.30.18.AM.mov |
); | ||
if (value !== SELECT_ALL_VALUE) { | ||
return ( | ||
<Tag onMouseDown={onPreventMouseDown} {...props}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To get rid of the typescript error:
<Tag onMouseDown={onPreventMouseDown} {...props}> | |
<Tag onMouseDown={onPreventMouseDown} {...(props as object)}> |
@@ -527,7 +527,7 @@ const AsyncSelect = forwardRef( | |||
) | |||
} | |||
oneLine={oneLine} | |||
tagRender={oneLine ? oneLineTagRender : undefined} | |||
tagRender={customTagRender} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, we only used a custom tag renderer if oneLine
was true. Does customTagRender
preserve the same behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes customTagRender
is the same as oneLineTagRender
. It has the same behaviour except it does not render the select all tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I mean to ask is if customTagRender
has the same behavior as tagRender={undefined}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see. The only difference between customTagRender
and the default is the inclusion of the onMouseDown
handler that prevents the dropdown from opening when clicking the tag icons. This was added for the oneLine
mode and it seemed useful for the regular use case, but i can add a check to not include it when the component is not in oneLine
mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I like the behavior. No change is needed then.
…elect-all-synchronous-select
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you for all the hard work and for addressing all the comments. This feature is a nice addition to the component!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why @michael-s-molina 's review didn't light up the merge button. Adding another approval to see if it unblocks.
Ephemeral environment shutdown and build artifacts deleted. |
@cccs-RyanK and @michael-s-molina I was wondering whether this feature could be configurable, especially as it pertains to SQL Lab. For example at Airbnb we have namespaces which house thousands of tables/views (see attachment) and if the user accidentally chooses the It's unclear if this option really has any value in the context of SQL Lab, i.e., I'm struggling to foresee a scenario when one would ever needs to see the schema for all the tables/views within a namespace as opposed to selecting the subset to entities they're interested in. |
I think it makes sense to disable the Select All option in that context. |
I agree with @michael-s-molina , let's disable it in that particular context. |
SUMMARY
This PR adds a 'select all' functionality to the synchronous Select component. This functionality has been requested by a large number of users and contributors. The select component has been previously split into sync and async components to simplify the code. The sync select component is the more widely used component, and a select all for the sync case is much easier to implement. This PR simply adds the option for selectAllEnabled only when the select component is in multi-select mode. The option is by default set to false. This is part of the greater task to rework the select component for the select all functionality outlined by @michael-s-molina in this PR: #20143
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TESTING INSTRUCTIONS
In storybook, go to the select component -> interactive select and set the mode to multi and selectAllEnabled to True
ADDITIONAL INFORMATION