feat: add search highlight/expand and "no tags" message [FC-0036] - #799
Conversation
|
Thanks for the pull request, @rpenido! Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket as you can:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
| useEffect(() => { | ||
| setNumPages(1); | ||
| } | ||
| }, [searchTerm]); |
There was a problem hiding this comment.
This hook will be called every time searchTerm changes.
There was a problem hiding this comment.
So initially we had this as a useEffect, however we opted for this approach instead after a discussion on a previous PR, since React discourages the use of useEffect in this manner as it causes extra re-renders: https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes
There was a problem hiding this comment.
Thank you for the docs! I didn't know that this was the recommended way.
Reverted: 62022b5
| style={{ | ||
| minHeight: '44px', | ||
| }} | ||
| {tagPages.isLoading ? ( |
There was a problem hiding this comment.
Changed tagPages from an array to an object that consolidates all pages. More info in the hook
| * @returns {{ | ||
| * hasMorePages: boolean, | ||
| * tagPages: { | ||
| * isLoading: boolean, | ||
| * isError: boolean, | ||
| * data: TagListData[], | ||
| * }[], | ||
| * }} |
There was a problem hiding this comment.
Removing the return type makes it be inferred from the function return
| const preLoadedData = new Map(); | ||
|
|
||
| dataPages.forEach(result => { | ||
| const newTags = dataPages.map(result => { |
There was a problem hiding this comment.
This makes the newTags be correctly inferred from the return type.
| const flatTagPages = { | ||
| isLoading: tagPages.some(page => page.isLoading), | ||
| isError: tagPages.some(page => page.isError), | ||
| isSuccess: tagPages.every(page => page.isSuccess), | ||
| data: tagPages.flatMap(page => page.data), | ||
| }; | ||
|
|
||
| return { hasMorePages, tagPages: flatTagPages }; |
There was a problem hiding this comment.
I made this change trying to simplify the component side.
Also, I'm not sure why, a new tagPages is being generated every render (I don't think this useMemo is don't its job).
There was a problem hiding this comment.
Do you mean every time the searchTerm changes when you say every render? I can't remember if this issue was happening before.
There was a problem hiding this comment.
Every render. I got that when I added a useEffect with tagPages in the dependency array and updated an state in the hook. It caused a render loop. But I don't think this is a problem now.
yusuf-musleh
left a comment
There was a problem hiding this comment.
@rpenido Great work! It works well upon testing it. I left a few comments/suggestions.
| useEffect(() => { | ||
| setNumPages(1); | ||
| } | ||
| }, [searchTerm]); |
There was a problem hiding this comment.
So initially we had this as a useEffect, however we opted for this approach instead after a discussion on a previous PR, since React discourages the use of useEffect in this manner as it causes extra re-renders: https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes
| const parts = text.split(new RegExp(`(${highlight})`, 'gi')); | ||
| return ( | ||
| <span> | ||
| {parts.map((part) => (part.toLowerCase() === highlight.toLowerCase() ? <span className="bg-accent-b">{part}</span> : part))} |
There was a problem hiding this comment.
This needs to have a unique key attribute, there are warnings in the console when I perform a search.
| useEffect(() => { | ||
| if (tagPages.isSuccess) { | ||
| if (searchTerm) { | ||
| const expandAll = tagPages.data.reduce( | ||
| (acc, tagData) => ({ | ||
| ...acc, | ||
| [tagData.value]: !!tagData.childCount, | ||
| }), | ||
| {}, | ||
| ); | ||
| setDropdownStates(expandAll); | ||
| } else { | ||
| setDropdownStates({}); | ||
| } | ||
| } | ||
| }, [searchTerm, tagPages.isSuccess]); | ||
|
|
There was a problem hiding this comment.
I could be mistaken if this is the right approach, but I think this could also be achieved without the use of useEffect, if you use the condition from the previous code that checks of the searchTerm has changed and add the logic there. Here is a semi-working solution just to get the idea across:
const [prevSearchTerm, setPrevSearchTerm] = useState(searchTerm);
// Reset the page and tags state when search term changes
// and store search term to compare
if (prevSearchTerm !== searchTerm) {
setPrevSearchTerm(searchTerm);
setNumPages(1);
if (tagPages.isSuccess) {
if (searchTerm) {
const expandAll = tagPages.data.reduce(
(acc, tagData) => ({
...acc,
[tagData.value]: !!tagData.childCount,
}),
{},
);
setDropdownStates(expandAll);
} else {
setDropdownStates({});
}
}
}This code doesn't correctly expand all the tags, just a demonstration for what I mean, but needs adjustments if this is the route we want to take.
There was a problem hiding this comment.
I'm afraid of this path because it could run this code before the API return (tagPages.isSuccess === False) and will not run again when the isSuccess changes.
| const flatTagPages = { | ||
| isLoading: tagPages.some(page => page.isLoading), | ||
| isError: tagPages.some(page => page.isError), | ||
| isSuccess: tagPages.every(page => page.isSuccess), | ||
| data: tagPages.flatMap(page => page.data), | ||
| }; | ||
|
|
||
| return { hasMorePages, tagPages: flatTagPages }; |
There was a problem hiding this comment.
Do you mean every time the searchTerm changes when you say every render? I can't remember if this issue was happening before.
|
|
||
| import { useTaxonomyTagsData } from './data/apiHooks'; | ||
|
|
||
| const HighlightedText = ({ text, highlight }) => { |
There was a problem hiding this comment.
I like the yellow highlighted text! It familiar to how chrome matches things you search on. However I double checked with the Figma design, it seems like it includes "bolding" of the matching text instead.
fa54099 to
1d44c8a
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #799 +/- ##
=======================================
Coverage 90.58% 90.58%
=======================================
Files 511 511
Lines 8879 8902 +23
Branches 1912 1919 +7
=======================================
+ Hits 8043 8064 +21
- Misses 811 813 +2
Partials 25 25 ☔ View full report in Codecov by Sentry. |
1d44c8a to
979d585
Compare
|
Could you take another look here @yusuf-musleh? |
There was a problem hiding this comment.
👍 @rpenido Looks good to me!
- I tested this: Testing it out locally, its working well
- I read through the code
- I checked for accessibility issues
- Includes documentation
-
I made sure any change in configuration variables is reflected in the corresponding client'sconfiguration-securerepository.
|
Rebased @xitij2000! |
One small thing, I should have noticed this before. I don't think "fix" is the correct category for this change. It is definitely a feature. Please update the PR title and commit message, and I will merge it. Sorry for not noticing this sooner. |
bcd501f to
74a1684
Compare
|
You're right @xitij2000! Thank you! |
|
@rpenido 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
Description
This PR makes minor improvements in the search taxonomy UI.
Suporting Information
Testing instructions
Open the tagging drawer and check the search responses to different queries
Private-ref: FAL-3615