-
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): keep options order when not in async mode #19085
Conversation
@ktmud Is it possible to fix the Explore issue first and leave the discussion of changing Select order to a follow-up PR? We'll probably need design input about this and I fear the discussion may delay the bug fix. |
c6aa009
to
30b3d2b
Compare
@michael-s-molina I'd be happy to wait and hear counter arguments for this change. Fixing just the Explore controls may lead to even more complexity which I'd be hesitant to dive into. |
15c7d22
to
5ff71e9
Compare
Another thing to call out is #17638 also changed the This PR reverts this behavior so that users always see columns in the order as they appear in table schema. Before this PRFor the "birth_names" dataset: After this PR and before #17638 |
abf20fb
to
46a9d0e
Compare
Codecov Report
@@ Coverage Diff @@
## master #19085 +/- ##
=======================================
Coverage 66.52% 66.52%
=======================================
Files 1646 1646
Lines 63540 63538 -2
Branches 6466 6465 -1
=======================================
+ Hits 42268 42270 +2
+ Misses 19596 19595 -1
+ Partials 1676 1673 -3
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
a55e4ff
to
24616b2
Compare
@michael-s-molina I managed to keep the sorting selected to top behavior while achieving the main goal of this PR--preserving the input order of predefined options list so that we don't have to provide custom sortComparator but rather reuse the default match sorter instead. I've also updated the PR description accordingly. Can you PTAL? Thanks! |
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
import isEqualArray from './isEqualArray'; |
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.
Basically a faster version of lodash.isEqual
where we only compare items in arrays shallowly. Also used in Table chart.
moment.tz(currentDate, b.timezoneName).utcOffset(); | ||
|
||
// pre-sort timezone options | ||
TIMEZONE_OPTIONS.sort(TIMEZONE_OPTIONS_SORT_COMPARTOR); |
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.
Select control now expects options
to be pre-sorted.
@@ -23,9 +23,11 @@ export default function isEqualArray<T extends unknown[] | undefined | null>( | |||
return ( | |||
arrA === arrB || | |||
(!arrA && !arrB) || | |||
(arrA && | |||
!!( |
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.
Making sure return result is always boolean
nextProps.choices !== this.props.choices || | ||
nextProps.options !== this.props.options | ||
!isEqualArray(nextProps.choices, this.props.choices) || | ||
!isEqualArray(nextProps.options, this.props.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.
Had to run this deeper check because mapStateToProps may create columns list with a new array but same content. We may need to dig deeper to those excessive rerendering and check whether they are actually necessary.
@@ -37,9 +37,9 @@ const defaultProps = { | |||
}; | |||
|
|||
const options = [ | |||
{ value: '1 year ago', label: '1 year ago', order: 0 }, | |||
{ value: '1 week ago', label: '1 week ago', order: 1 }, | |||
{ value: 'today', label: 'today', order: 2 }, |
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.
May do a bigger sweep in other components to clean up similar order
props later.
}); | ||
|
||
test('displays the original order when unselecting', async () => { | ||
// eslint-disable-next-line jest/expect-expect |
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.
May I suggest renaming checkOrder
to matchOrder
, and returning a boolean
? This way we could have the expect
clauses inside the tests and avoid disabling lint rules.
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 suggestion!
userEvent.click(await findSelectOption(option3)); | ||
userEvent.click(await findSelectOption(option8)); | ||
userEvent.click(await findSelectOption(originalLabels[1])); | ||
// after selection, keep the original order |
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.
Nice improvement to the test!
sortSelectedFirst(a, b) || | ||
// Only apply the custom sorter in async mode because we should | ||
// preserve the options order as much as possible. | ||
(isAsync ? sortComparator(a, b, '') : 0), |
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.
Can we add the following docs (or something similar) to sortComparator
?
export interface SelectProps extends PickedSelectProps {
...
/**
* Custom sorting comparator for the options.
* Works in async mode only.
*/
sortComparator?: typeof DEFAULT_SORT_COMPARATOR;
If you check the references to |
@ktmud Thanks for clearly documenting changes in code or comments. This helps a lot with the review and code readability. I'll try to execute some tests tomorrow to make sure we didn't break anything. |
@michael-s-molina I cleaned up all references of |
e4959f4
to
17a1363
Compare
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. Thanks for the improvements!
17a1363
to
4c0bc70
Compare
(cherry picked from commit ae13d83)
SUMMARY
After applying a more sensible search sort comparator in #18856 , I realized that the new sorting isn't applied to non-async select options in Explore controls. This is because they are using a default sort comparator added to Explore's Select control in #17638, which was trying to address the issue where options are unnecessarily sorted by labels for numeric values.
In reality, we can get away with the problem raised in #17638 by simply not messing with the input option orders when users are not searching. The options have two sorted orders:
By preserving the original order of input
options
, we avoid having to add custom sorters in most cases. When users are not searching, we just use whatever orders options provider pass in; when users are searching, we apply the same match sort algorithm for maximum consistency. Sorting the unfiltered options list only makes sense when merge async results from different search queries or multiple pages where the orders of the options in the merged list aren't guaranteed. For this case, we can introduce amergeData
config function to indicate how data should be merged in the frontend---the order of the merged data will still be preserved when the search string is empty.This PR changes the Select component to not reorder the predefined
options
list when in non-async mode, which is also the original behavior of the now deprecated Select component based on react-select.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Before
Search sort exact match and starts with first isn't applied to countries select in Country Map
Numeric values are correctly sorted and selected values will be pushed to the top:
After
Countries can be filtered with the improved sort:
Numbers are still correctly sorted and selected values will not be pushed to the top:
Multi select will still sort selected values to the top (same as before):
TESTING INSTRUCTIONS
Test the select controls in different chart types
ADDITIONAL INFORMATION