Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions src/hooks/useApproveOnlyRoleBlockedModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Subscribes to BLOCKED_ROLE_CHANGE in Onyx and shows the blocked-reasons modal on the global modal stack
* when the backend refuses an approve-only role change.
*/
import {clearBlockedRoleChange, clearUpdateMemberRoleError} from '@userActions/Policy/Member';
import {clearBlockedRoleChange} from '@userActions/Policy/Member';

import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
Expand Down Expand Up @@ -47,17 +47,7 @@ function useApproveOnlyRoleBlockedModal() {
lastShownRef.current = blockedRoleChange;
isModalOpenRef.current = true;

const {policyID, email, blockedReasons = []} = blockedRoleChange;

// `OnyxUpdates.apply` runs `request.failureData` on the microtask after `response.onyxData`, which sets a
// generic inline error on the member row. Clear that row error once `failureData` has settled so the modal
// is the only feedback shown for a blocked role change.
if (policyID && email) {
Promise.resolve().then(() => {
clearUpdateMemberRoleError(policyID, email);
});
}

const {blockedReasons = []} = blockedRoleChange;
const reasonLines = blockedReasons.filter((reason) => reason in REASON_TRANSLATION_KEYS).map((reason) => `• ${translate(REASON_TRANSLATION_KEYS[reason])}`);
const hasReasonLines = reasonLines.length > 0;

Expand Down
6 changes: 4 additions & 2 deletions src/libs/actions/Policy/Member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,8 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
},
];

// Roles that cannot create expenses show a dedicated modal on refusal, so skip inline row errors.
const canCreateExpenses = canRoleCreateExpenses(newRole);
const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY | typeof ONYXKEYS.COLLECTION.REPORT>> = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand All @@ -658,8 +660,8 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
// eslint-disable-next-line no-param-reassign
member[current.email] = {
...(previousEmployeeList[current.email] ?? {}),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.editor.genericFailureMessage'),
pendingAction: canCreateExpenses ? CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE : null,
...(canCreateExpenses && {errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.editor.genericFailureMessage')}),
};
return member;
}, {}),
Expand Down
58 changes: 58 additions & 0 deletions tests/actions/PolicyMemberTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,64 @@ describe('actions/PolicyMember', () => {
});
});
});

it('does not set errors in failureData when changing role to approve-only', () => {
const member1 = '[email protected]';
const member2 = '[email protected]';
const fakePolicy: PolicyType = {
...createRandomPolicy(0, CONST.POLICY.TYPE.CORPORATE),
employeeList: {
[member1]: {
email: member1,
role: CONST.POLICY.ROLE.USER,
},
[member2]: {
email: member2,
role: CONST.POLICY.ROLE.USER,
},
},
};

const approveOnlyData = Member.buildUpdateWorkspaceMembersRoleOnyxData(fakePolicy, [member1, member2], [1, 2], CONST.POLICY.ROLE.APPROVE_ONLY);
expect(approveOnlyData.failureData).toEqual(
expect.arrayContaining([
expect.objectContaining({
key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`,
value: expect.objectContaining({
employeeList: {
[member1]: {
email: member1,
role: CONST.POLICY.ROLE.USER,
pendingAction: null,
},
[member2]: {
email: member2,
role: CONST.POLICY.ROLE.USER,
pendingAction: null,
},
},
}),
}),
]),
);

const adminData = Member.buildUpdateWorkspaceMembersRoleOnyxData(fakePolicy, [member1], [1], CONST.POLICY.ROLE.ADMIN);
expect(adminData.failureData).toEqual(
expect.arrayContaining([
expect.objectContaining({
key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`,
value: expect.objectContaining({
employeeList: expect.objectContaining({
[member1]: expect.objectContaining({
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
errors: TestHelper.anyObject,
}),
}),
}),
}),
]),
);
});
});
describe('requestWorkspaceOwnerChange', () => {
it('Change the workspace`s owner', async () => {
Expand Down
Loading