-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Add missing multi tag view #41351
Add missing multi tag view #41351
Conversation
@ikevin127 is going to jump on this for us. Thanks! |
@s77rt did you ensure that if there's only one level of tag, the UI remains as it is today in production on the Tags page? |
@trjExpensify Yes that area is not touched |
🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪 |
This comment was marked as resolved.
This comment was marked as resolved.
Nice work picking this up! It's testing quite well for me on that adhoc build: 2024-05-01_00-09-32.mp4Few things to note:
CC: @dubielzyk-expensify @JmillsExpensify
|
Reviewer Checklist
Screenshots/VideosAndroid: NativeAndroid: mWeb ChromeiOS: NativeiOS: mWeb SafariMacOS: Chrome / Safari *Screen.Recording.2024-04-30.at.20.02.16.movMacOS: Desktop |
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 tested #41279 expected results steps:
- ✅ When more than one of
Classes
,Customers/Projects
orLocations
are selected for import, the Tags page table will represent each distinct tag level imported from QBO. - ✅ If the tag level is required,
Required
will be added to the status column in the table instead ofEnabled
||Disabled
. - ✅ Behind the "Settings" button on the
Tags
page header in the RHP:
3a. The toggle for "Members must tag all spend" will remain, allowing users to bulk toggle on/off making all tag levels mandatory.
3b.⚠️ theCustom tag name
field will be removed; users will be able to set theCustom tag name
a level deeper for each of the tag levels (see 4b. below). - ✅ Clicking on a tag level name in the table will open the RHP, which will contain:
4a. ARequired
toggle, when enabled it makes the tag level required coding on the workspace and setsRequired
in the mainTags
page table.
4b.⚠️ ACustom tag name
> push input row, that opens a simple "Custom tag name" page with a text input to rename the tag level.
4c. A list of all of the tag values for that tag level (that opens up the individual tag value edit page with the same permissions and logic that exists today).
4d. checkboxes right-aligned each of the tag values to facilitate bulk select capabilities via the[Selected X v]
button with the same permissions and logic that exists today.
✅ Additionally -> Tags that are not multi-tag are working just like before.
All the steps test well and the implementation works as expected.
Regarding the
Now regarding
- If we click on
Classes
main tag then click on any of theClasses
sub-tags -> we get "Page not found" in RHP. This does not happen with theCustomers/Projects
main tag sub-tags.
Video - Issue 1
issue-1.mov
- If we click on
Classes
main tag, we can observe sub-tags with&
symbol in their name which is not decoded into&
(ampersand) and we're left with sub-tag labels likeR&D
instead ofR&D
. Additionally, if click on this we also get the RHP "Page not found" and the URL param looks weird as it's actually encoding the labelR&D
which is url encoded toR%26amp%3BD
instead of encoding decoded labelR&D
which should result in url encodedR%26D
.
Video - Issue 2
issue-2.mov
❗ Now I'm not sure if these should be PR blockers or we're good to move forward despide these issues. If we're good, then we can move forward - otherwise these issues should be fixed before this is merged.
We did not find an internal engineer to review this PR, trying to assign a random engineer to #41279 as well as to this PR... Please reach out for help on Slack if no one gets assigned! |
@@ -59,7 +59,7 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { | |||
}, | |||
]; | |||
|
|||
if (policy?.connections?.quickbooksOnline.data.country !== CONST.COUNTRY.US) { | |||
if (policy?.connections?.quickbooksOnline?.data?.country !== CONST.COUNTRY.US) { |
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.
Why is this change needed? TS does not report that these optional chaining operators are necessary.
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.
thanks for the context! Let's update the TS types for data and country to be optional then? to make sure that we're safely accessing them everywhere, not just 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.
I have updated the type for data
to be optional. We need to do the same for the Connection
object: both quickbooksOnline
and xero
are optional. Tried to make that change here but caused ts errors on updatePolicyConnectionConfig
. Let's create a separate issue to handle that
}, [isFocused]); | ||
|
||
const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags).filter((policy) => policy.name === currentTagListName), [currentTagListName, policyTags]); | ||
const tagList = useMemo<PolicyForList[]>( |
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.
IMO this can be made much more readable, and also significantly reduce our type coercion using an implementation like this:
const tagList = useMemo<PolicyForList[]>(
() =>
policyTagLists
.map((policyTagList) => Object.values(policyTagList.tags))
.flat()
.sort((tagA, tagB) => localeCompare(tagA.name, tagB.name))
.map((tag) => ({
value: tag.name,
text: PolicyUtils.getCleanedTagName(tag.name),
keyForList: tag.name,
isSelected: selectedTags[tag.name],
pendingAction: tag.pendingAction,
errors: tag.errors ?? undefined,
enabled: tag.enabled,
isDisabled: tag.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
rightElement: <RightElementEnabledStatus enabled={tag.enabled} />,
})),
[policyTagLists, selectedTags],
);
Also, I can't help but notice that this is exactly the same as the other file. So let's DRY this up by moving it to a util function.
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 didn't get the time to look into this one. I can handle later if we don't have to merge today otherwise it can be done in a follow up
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.
Some other high-level feedback on this PR is that it seems like there's a lot more room to optimize things:
- don't re-create an object that shadows an array on every render, use memoization and generate them at the same time
- don't copy-paste large segments of code. let's try to put in some work to do a reasonable amount of DRY
- question your type casts. Try removing them and see what happens. we should often be able to rely on type inference, and if need to cast types it's often a sign that something could be simplified. For example by using native array sorting rather than
lodashSortBy
(which is slower and mangles types) - generally I try to avoid creating functions that just contain render logic and calling them on every render. Usually a better pattern is to store the JSX element(s) that we want to render in variables and use
useMemo
to encapsulate the more complex render logic. It's the same level of work and readability, with better memoization often leading to better performance.
(btw @s77rt I know you took over this PR from @narefyev91, so hopefully this feedback is helpful to him as well) |
Yeah! But most of your comments related to already existed code :-) |
@MonilBhavsar @luacmartins I seem to remember you guys having some experience with this from categories. Context:
|
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.
Chatted about this in slack, but let's please make the two changes I requested here
I have pushed changes for the types. I didn't add a comment as it will only explain the what not the why. |
I was curious how this PR is going. I haven't checked the code but the UI looking really nice! Screen.Recording.2024-05-10.at.2.03.31.PM.mov |
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.
otherwise LGTM 👍🏼
✋ 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/roryabraham in version: 1.4.73-0 🚀
|
Why wasn't this PR tested on mobile? It created this deploy blocker here for example: #42059 |
Sorry my bad! I have raised a PR fixing the regression |
🚀 Deployed to production by https://github.com/Beamanator in version: 1.4.73-7 🚀
|
Details
Fixed Issues
$ #41279
PROPOSAL:
Tests
Classes
andCustomers/Projects
Classes
andCustomers/Projects
Offline tests
N/A
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 methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.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: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
web.mov
MacOS: Desktop