Move multi-level tag Required from the Tags table to Rules - #98414
Move multi-level tag Required from the Tags table to Rules#98414Krishna2323 wants to merge 22 commits into
Conversation
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
|
@MelvinBot review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62ceef335c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
|
Reviewed the changes. The overall approach is clean — gating the old Required column/switches/bulk-actions behind 🐛 Per-level toggles render stale (all-off) after a delayed tag loadThis is exactly testing step 10 (fresh login / hard refresh → go straight to Rules → General → Require fields). The sync effect is one-shot per
Suggested fix: sync ❓ "Can't make all tag lists optional" guard is dropped for independent multi-level tagsOn the old Tags table, toggling off the last required list is hard-blocked with the Nothing else blocking from my read. Happy to implement either fix — reply with |
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
…s section Signed-off-by: krishna2323 <belivethatkg@gmail.com>
|
🚧 JmillsExpensify has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@JmillsExpensify could you please share the steps you followed? Did you use the |
|
Not sure on the steps, but it's a workspace connected to NetSuite I added him to owned by
I guess I'm not really following this screen, why would making a tag level required or not be locked? I understand the category one because we force you to minimally categorise expenses.
|
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@MelvinBot review and also check if there are any behavioral changes. |
|
Failure scenario is not working correctly. Precondition: Simulate network failing requests
Category works better but still has bug: toggle reverts to off but no RBR feedback Screen.Recording.2026-08-14.at.5.28.05.PM.mov |
|
Bug: A mixed require/unrequire save wipes the newly added violation
Screen.Recording.2026-08-14.at.5.40.03.PM.mov |
|
#97639 bug regressed Screen.Recording.2026-08-14.at.5.47.07.PM.mov
|
| const isTagToggleDisabled = isTagFeatureDisabled || !hasEnabledTags || isConnectedToAccounting; | ||
| // For independent multi-level tags, Required is configured per level in each tag list's RHP, so the policy-wide toggle is hidden (same gate as WorkspaceTagsSettingsPage). | ||
| const shouldShowTagToggle = !isMultiLevelTagsUtil(policyTags) || hasDependentTagsUtil(policy, policyTags); | ||
| // A connection owns the tag lists, not whether an expense must carry one, so it doesn't lock this the way it locks | ||
| // Categories. The Tags table, tag list page and Tags settings all left Required editable while connected. | ||
| const isTagToggleDisabled = isTagFeatureDisabled || !hasEnabledTags; |
There was a problem hiding this comment.
Was there a discussion for this?
In production, there's no way to enable multi-level tags when account connected
There was a problem hiding this comment.
We can enable/disable tags when account is connected, the tags need to be imported before we connect to account. See #98414 (comment)
Monosnap.screencast.2026-08-15.00-14-45.mp4
| const [tagRequiredByLevel, setTagRequiredByLevel] = useState<Record<number, boolean>>({}); | ||
| const syncedPolicyIDRef = useRef<string | undefined>(undefined); | ||
|
|
||
| const getLevelRequired = useCallback((orderWeight: number, isRequiredOnList: boolean | undefined) => tagRequiredByLevel[orderWeight] ?? !!isRequiredOnList, [tagRequiredByLevel]); |
There was a problem hiding this comment.
Both params are from the same object.
getLevelRequired(tagList) is strictly better and shortens every call site.
There was a problem hiding this comment.
threaded the tag list through isLastRequiredLevel and handleTagListRequiredToggle.
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
fixed Monosnap.screencast.2026-08-14.23-50-40.mp4
Fixed, category has no RBR on staging also (leagcy). Monosnap.screencast.2026-08-14.23-54-16.mp4
Fixed: Monosnap.screencast.2026-08-15.00-09-20.mp4
Fixed Monosnap.screencast.2026-08-15.00-12-44.mp4 |
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Monosnap.screencast.2026-08-16.23-05-13.mp4 |
|
@situchan could you please prioritize this when you get a chance? Thanks! |
|
Optimistic violations are still not working properly. Both category and tag Screen.Recording.2026-08-17.at.8.06.52.PM.mov |
|
Bug: Tag can be enabled but cannot be disabled back. Screen.Recording.2026-08-17.at.8.11.04.PM.mov |
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Fixed |
Same reproducible on staging also: Monosnap.screencast.2026-08-18.01-22-43.mp4 |
ok, looks like there's no way to set |
|
There's still bug in optimistic violation but I reproduced this in production as well. So I think we can fix this separately, not blocking Rules feature.
Screen.Recording.2026-08-17.at.9.14.49.PM.mov |
ReviewOverall this is a well-structured change — the hard part (recomputing violations once from the combined end state, and splitting a mixed require/optional save into one request per direction so the last write can't clobber the others) is handled carefully and the comments explain the "why" well. I traced the new action ( 🐛 A required level whose tags are all disabled can't be turned off
isActive={getLevelRequired(tagList) && areLevelTagsEnabled}For a level that is already Required but currently has all of its tags disabled (
This directly contradicts testing step 9 ("If Region is already required, verify its toggle remains interactive so it can be turned off") — it's interactive but not actually turn-off-able. The isActive={getLevelRequired(tagList)}Truth table after the suggested change
Minor / non-blocking
I focused on a static code review (didn't set up a live Control workspace with |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ccfea93255
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Beta on/off regression analysisBeta OFF matches production ✅ (one ungated exception, noted below). I traced every one of the 12 changed files and confirmed each behavioral change is either rendered only inside revamp-only pages/components or guarded by an explicit Beta ON has one real regression — the required-level toggle bug I flagged in the earlier review is still the main one. Beta-OFF gating — how each change is neutralized
|
Signed-off-by: krishna2323 <belivethatkg@gmail.com>


Explanation of Change
Fixed Issues
$ #95764
PROPOSAL:
Tests
Testing steps
Per-level Required — independent multi-level tags
rulesRevampenabled, create two independent tag lists (e.g. State, Region), each with enabled tags.Single/dependent tags
Disabled tag levels
Tags load without visiting Tags
Required removed from Tags table (beta on)
Beta off
rulesRevampand verify all existing Required controls/actions return and work, including the warning when making the last required tag list optional.Offline tests
QA Steps
Same as tests
Verify that no errors appear in the JS console
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
android_hybrid.mp4
Android: mWeb Chrome
android_mWeb.mp4
iOS: Native
ios_hybrid.mp4
iOS: mWeb Safari
ios_mWeb.mp4
MacOS: Chrome / Safari
web_chrome.mp4