Repository navigation
Open
Labels
EngineeringImprovementItem broken or needs improvement.Item broken or needs improvement.ReviewingHas a PR in reviewHas a PR in reviewWeeklyKSv2KSv2
Description
Here is the,
- Parent GH tracking issue - https://github.com/Expensify/Expensify/issues/673366
- Design doc - https://docs.google.com/document/d/1FuiUnLfrGz4lrmnb2naCDMY0j-ghmQOklNVcyzkBzBI/edit?tab=t.0#heading=h.6ga7zvbxi2ha
Before starting: review your section of the design doc first. If it has any pending comments, let's discuss them before work begins so everyone is on the same page.
PURPOSE
Render the POLICYCHANGELOG_SET_CATEGORY_VISIBILITY entries Auth posts to #admins (1.17), in the format "{set|changed} {members} to {only} see {categories}", with long lists shown in full at the top of the entry's thread.
Auth sends each entry as data (categoryNames, accountIDs, hadRestriction, reason), not as text. The App builds the sentence when it renders the entry, like every other category change log, so it's translated into the viewer's language and shows members' current names.
A mock of how the App will display this is,
SOLUTION
- Add
SET_CATEGORY_VISIBILITY: 'POLICYCHANGELOG_SET_CATEGORY_VISIBILITY'toCONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG. - Add
categoryNames?: string[],accountIDs?: number[],hadRestriction: booleanandreason: 'setByAdmin' | 'categoriesDeleted' | 'categoriesDisabled'toOriginalMessagePolicyChangeLog. - Add the new action to
isCategoryModificationAction, so the LHN preview and copy-to-clipboard use the same message, and map it tocategoryResolverinPOLICY_CHANGE_LOG_RESOLVERS. - In
getWorkspaceCategoryUpdateMessage, add a branch for the new action, before the fallback here:- Build the categories text:
- When
categoryNamesis[]: no categories text, since the entry usesclearedCategoryVisibility. - When it has 10 or more:
categoryCount("14 categories"). - Otherwise: each name in quotes, joined with
formatList, which adds the serial "and", asoneCategoryfor one name (the "Meals" category) orsomeCategoriesfor more (the "Meals" and "Travel" categories).
- When
- Build the members text the same way: "everyone" for
[], "{count} members" for 10 or more, otherwise display names fromgetDisplayNameForParticipantjoined withformatList. - When the entry is shown as its thread's parent action (
ReportActionItemParentAction), return the full lists instead: a "Categories: …" line and/or a "Members: …" line, one for each list with 10 or more entries, naming every item. Pass this as a newshouldShowFullListparam ofgetWorkspaceCategoryUpdateMessage, set only from that component. - Otherwise, return
setCategoryVisibility("set {members} to only see {categories}"), orchangedCategoryVisibility("changed …") whenhadRestrictionistrue. WhencategoryNamesis[], returnclearedCategoryVisibility("changed {members} to see all categories") instead. Follow it with the reason sentence forcategoriesDeletedandcategoriesDisabled.
- Build the categories text:
- Add the copy to
workspaceActionsinen.ts. We'll handle the translations for the other languages in the GitHub issue.setCategoryVisibility:"set {members} to only see {categories}",changedCategoryVisibility:"changed {members} to only see {categories}",clearedCategoryVisibility:"changed {members} to see all categories"oneCategory:"the {name} category",someCategories:"the {list} categories",everyone:"everyone",categoryCount:"{count} categories",memberCount:"{count} members"categoryVisibilityCategoriesList:"Categories: {list}",categoryVisibilityMembersList:"Members: {list}"categoryVisibilityReasonDeleted:", since their only category was deleted. Update their category visibility if needed."categoryVisibilityReasonDisabled:", since their only category was disabled. Update their category visibility if needed."
Examples, matching the 1.17 entries:
| Change | #admins entry | Top of its thread |
|---|---|---|
| Admin restricts Bob, who had no restriction, to Meals and Fuel | set Bob Sterling to only see the "Meals" and "Fuel" categories | None |
| Admin gives Bob, who was restricted, every enabled category | changed Bob Sterling to see all categories | None |
| Admin restricts every member to Meals and Fuel, when no one had a restriction | set everyone to only see the "Meals" and "Fuel" categories | None |
| Admin changes Cathy's restriction to 14 categories | changed Cathy Langford to only see 14 categories | Categories: "Advertising", "Airfare", "Benefits", ... |
| Admin restricts 12 members, none restricted before, to Fees | set 12 members to only see the "Fees" category | Members: Alice Monroe, Ben Carter, Bob Sterling, ... |
| Bob's only category, Fuel, is deleted | changed Bob Sterling to see all categories, since their only category was deleted. Update their category visibility if needed. | None |
| Bob's only category, Fuel, is disabled by a sync | changed Bob Sterling to see all categories, since their only category was disabled. Update their category visibility if needed. | None |
MANUAL TEST STEPS
- Restrict an unrestricted member to Meals and Fuel, and confirm #admins shows "set {member} to only see the "Meals" and "Fuel" categories", and the LHN preview shows the same text.
- Restrict them to only Meals, and confirm the entry reads "changed {member} to only see the "Meals" category".
- Give the member every enabled category, and confirm the entry reads "changed {member} to see all categories".
- Restrict a member to 10 or more categories, and confirm the entry shows the count, and opening its thread shows every category at the top.
- Delete a member's only visible category, and confirm the admin's entry reads "changed {member} to see all categories, since their only category was deleted. Update their category visibility if needed."
Issue Owner
Current Issue Owner: @daledahMetadata
Metadata
Labels
EngineeringImprovementItem broken or needs improvement.Item broken or needs improvement.ReviewingHas a PR in reviewHas a PR in reviewWeeklyKSv2KSv2
Activity
huult commentedon Oct 30, 2026
Per my discussion with @chiragsalian and the comment here, I'll assign this ticket to myself as a C+.
huult commentedon Oct 30, 2026
This ticket can be implemented by MelvinBot. @MelvinBot, please post a proposal.
MelvinBot commentedon Oct 30, 2026
Proposal
What is the root cause of that problem?
POLICYCHANGELOG_SET_CATEGORY_VISIBILITYis a new action type that arrives as data, not text. The App has no constant for it, nooriginalMessagefields, and no branch ingetWorkspaceCategoryUpdateMessage. Any unknown category action falls through togetReportActionText(action)at line 3922.What changes do you think we should make in order to solve the problem?
I'll follow the issue's solution, with three adjustments based on the current code.
SET_CATEGORY_VISIBILITYtoPOLICY_CHANGE_LOG. AddcategoryNames,accountIDs,hadRestrictionandreasontoOriginalMessagePolicyChangeLog.isCategoryModificationAction. That gives the LHN preview, thread title and copy-to-clipboard the short message. Map it tocategoryResolverinPOLICY_CHANGE_LOG_RESOLVERS.getWorkspaceCategoryUpdateMessage:[],categoryCountfor 10 or more, otherwise quoted names joined withformatListasoneCategoryorsomeCategories.everyonefor[],memberCountfor 10 or more, otherwisegetDisplayNameForParticipantnames joined withformatList.setCategoryVisibility,changedCategoryVisibility(whenhadRestriction) orclearedCategoryVisibility(whencategoryNamesis[]). Append the reason sentence forcategoriesDeletedandcategoriesDisabled.shouldShowFullLististrue, return theCategories: …and/orMembers: …lines for any list with 10 or more items.ReportActionItemParentAction. Reuse the existingisThreadReportParentActionprop.AncestorReportActionItemalready sets it for the thread parent. Pass it fromReportActionItemtoActionContentRouter, then toPolicyChangeLogContent, then throughcategoryResolverasshouldShowFullList.workspaceActionsinen.ts. Two adjustments:quotedCategoryNamekey). Each locale can then use its own marks:"…"in en,„…“in de,« … »in fr.en, so they need the keys too or typecheck fails. I'll add them and let the translation workflow fill in the copy.getWorkspaceCategoryUpdateMessagetests. Also guard the branch against an emptyoriginalMessage, becausePolicyChangeLogContentTestrenders every type with{}.Open question for the C+ and internal engineer
AncestorReportActionItemsetsisThreadReportParentActionfor every ancestor shown above a thread, not only the direct parent. So a nested thread would show the full list for this entry too. That seems correct, but please confirm.What alternative solutions did you explore? (Optional)
Adding a new
shouldShowFullListprop starting inReportActionItemParentAction, as the issue suggests. It would duplicateisThreadReportParentAction, which already flows toReportActionItem.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/105085)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
huult commentedon Oct 30, 2026
@MelvinBot implement this to create a draft PR.
MelvinBot commentedon Oct 30, 2026
🤖 Draft PR created: Show category visibility change logs in #admins
Please mark it as "Ready for review" or ask me to do that for you when it is ready for review.
It follows the proposal. Two things need a human:
TestsandQAsections are left for you.view run
daledah commentedon Nov 5, 2026
I assigned myself since I’m also the C+ on the PR