-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Fix incorrect ordering of subcategories #29281
Fix incorrect ordering of subcategories #29281
Conversation
…/28964-incorrect-ordering-subcategories
…/28964-incorrect-ordering-subcategories
…/28964-incorrect-ordering-subcategories
…/28964-incorrect-ordering-subcategories
@BeeMargarida, I've applied your suggestions 🙂 |
@cubuspl42 @puneetlath One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
@cubuspl42 mind providing an ETA for when you'll be able to review? This is the last issue keeping us from removing the Categories beta and opening the feature to everyone, so I'm eager to finish 😄 |
@puneetlath Would tomorrow morning (in ~12 hours from now) work for you? |
Yes, that works. Thanks! |
src/libs/OptionsListUtils.js
Outdated
const hierarchy = {}; | ||
|
||
_.each(categories, (category) => { | ||
const path = category.name.replaceAll(CONST.PARENT_CHILD_SEPARATOR, '.'); |
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.
Is dot (.
) a forbidden character in the category name?
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.
Perhaps, but path
is not a category name anymore. It is keys for hierarchy's object.
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 meant is if it's guranateed that category.name
doesn't contain dots.
Example: Movies: Mr. Nobody
-> Movies
.
Mr
.
Nobody
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.
If you're not sure that Mr. Nobody
is not an invalid category name part, it would be a good idea to add such case to unit tests
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 got you. Actually, a good catch!
We need to test this case 🧐
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.
@cubuspl42, I've added logic to handle the case - 21a25fa.
I understood that this was a non-requirement for top-level categories to be sorted, as this was explicitly noted in tests. Originally:
After my suggestion to improve the language:
|
But maybe this is misunderstanding, and it actually was required? |
Ohhhh I see. I think this is a misunderstanding and we should sort the top-level categories. Sorry for any confusion! |
Okay, I will add this logic for sorting top-level categories. |
@puneetlath, in general, the sorting uses a JS feature with objects. It builds an object, where sets each category by Example: // Initial categories come from the backend =
const categories = {
Movies: {
name: "Movies",
enabled: true,
},
"Movies: Servant of the People": {
name: "Movies: Servant of the People",
enabled: true,
},
"Movies: Servant of the People: Season 1: Episode 1": {
name: "Movies: Servant of the People: Season 1: Episode 1",
enabled: true,
},
}
// The app coverts them to hierarchy
const hierarchy = {
Movies: {
name: "Movies",
"Servant of the People": {
name: "Servant of the People",
"Season 1": {
name: "Movies: Servant of the People: Season 1",
"Episode 1": {
name: "Movies: Servant of the People: Season 1: Episode 1",
}
}
}
}
} After that, the app iterates Does it make sense now? |
That makes sense! So then if we just add sorting for the top-level I think we'll be good to go. |
…/28964-incorrect-ordering-subcategories
@cubuspl42, @puneetlath, I've added the sorting of top-level categories. |
Ok great. @cubuspl42 if you can do a quick review, then I can do a final review and we can hopefully get this merged today! |
@rezkiy37 looks like you actually have a failing Jest test. |
@puneetlath, sorry, my bad. Just fixed 🙂 |
src/libs/OptionsListUtils.js
Outdated
*/ | ||
function sortCategories(categories) { | ||
// Sorts categories alphabetically by name. | ||
const sortedCategories = _.values(categories).sort((a, b) => { |
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.
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.
Done - 015cc04.
* } | ||
* } | ||
*/ | ||
_.each(sortedCategories, (category) => { |
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 used _.reduce
a few lines later, maybe this would be a bit cleaner if we used reduction instead of mutating the hierarchy
object?
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, I use the reduction to covert the hierarchy
object into a sorted array. Before the reduction, we need do 2 actions:
- Sort all categories alphabetically. It helps with top-level categories.
- Build the
hierarchy
object. It helps sort subcategories, keep them uniquely and store initial names.
So, I don't see a variant how to combine these 2 different functions.
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 just meant that the hierarchy
itself could probably also be built in a mostly functionally-pure way
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.
Hmmm... Could you please share an example?
It is a simple loop right now, where the app sets values one by one. I don't see any concerns with functional programming patterns here.
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.
Okey, let's leave this. I agree that the code is acceptable as-is.
src/libs/OptionsListUtils.js
Outdated
@@ -796,6 +870,15 @@ function getCategoryListSections(categories, recentlyUsedCategories, selectedOpt | |||
indexOffset += selectedOptions.length; | |||
} | |||
|
|||
const selectedOptionNames = _.map(selectedOptions, (selectedOption) => selectedOption.name); | |||
const filteredRecentlyUsedCategories = _.chain(recentlyUsedCategories) | |||
.filter((categoryName) => !_.includes(selectedOptionNames, categoryName) && lodashGet(categories, `${categoryName}.enabled`, false)) |
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.
Maybe let's use array-based lodashGet
here, as we modify this code (also a few lines later)
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 am not sure I understand what you want here.
Should we use lodashGet
instead of includes
? Actually, selectedOptions
and selectedOptionNames
are both arrays, therefore lodashGet
is not a good choice to iterate here.
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.
lodashGet(categories, `${categoryName}.enabled`)
It's just a follow-up to our earlier conclusions about using lodashGet
with a dot-based string argument. The variant which accepts an array is safer when the strings are dynamic.
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.
Ah, okay.
Done - 411db80.
…/28964-incorrect-ordering-subcategories
Great job! |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/puneetlath in version: 1.3.91-0 🚀
|
🚀 Deployed to production by https://github.com/marcaaron in version: 1.3.91-8 🚀
|
Details
The PR fixes the ordering of categories and sub-categories.
Fixed Issues
$ #28964
PROPOSAL: N/A
Tests
Advice: before testing, please prepare a few workspaces with varying category lengths (<8 and >=8), levels of nesting, and sorting. There are no restrictions. Use OldDot to manipulate the category lists.
parent: child
relationship.Offline tests
Same as "Tests".
QA Steps
Same as "Tests".
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
Android.Large.mov
Android: mWeb Chrome
Android.Chrome.Large.mov
iOS: Native
IOS.Large.mov
iOS: mWeb Safari
IOS.Safari.Large.mov
MacOS: Chrome / Safari
MacOS: Desktop
Desktop.Large.mov