, policy: OnyxEntry;
};
const allPolicies: OnyxCollection = {};
@@ -407,7 +408,7 @@ function removeMembers(accountIDs: number[], policyID: string) {
API.write(WRITE_COMMANDS.DELETE_MEMBERS_FROM_WORKSPACE, params, {optimisticData, successData, failureData});
}
-function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newRole: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER) {
+function updateWorkspaceMembersRole(policyID: string, accountIDs: number[], newRole: ValueOf) {
const previousEmployeeList = {...allPolicies?.[policyID]?.employeeList};
const memberRoles: WorkspaceMembersRoleData[] = accountIDs.reduce((result: WorkspaceMembersRoleData[], accountID: number) => {
if (!allPersonalDetails?.[accountID]?.login) {
diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts
index bcfdaf696946..723bdbe1b137 100644
--- a/src/libs/actions/Task.ts
+++ b/src/libs/actions/Task.ts
@@ -1126,7 +1126,7 @@ function getTaskOwnerAccountID(taskReport: OnyxEntry): number
}
/**
- * Check if you're allowed to modify the task - anyone that has write access to the report can modify the task
+ * Check if you're allowed to modify the task - anyone that has write access to the report can modify the task, except auditor
*/
function canModifyTask(taskReport: OnyxEntry, sessionAccountID: number): boolean {
if (ReportUtils.isCanceledTaskReport(taskReport)) {
@@ -1143,7 +1143,7 @@ function canModifyTask(taskReport: OnyxEntry, sessionAccountID
return true;
}
- if (!ReportUtils.canWriteInReport(taskReport)) {
+ if (!ReportUtils.canWriteInReport(taskReport) || ReportUtils.isAuditor(taskReport)) {
return false;
}
diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index e686ec0bf513..9de547509762 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -6,6 +6,7 @@ import type {TextInput} from 'react-native';
import {InteractionManager, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
import Badge from '@components/Badge';
import Button from '@components/Button';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
@@ -336,9 +337,12 @@ function WorkspaceMembersPage({personalDetails, route, policy, currentUserPerson
const isOwner = policy?.owner === details.login;
const isAdmin = policyEmployee.role === CONST.POLICY.ROLE.ADMIN;
+ const isAuditor = policyEmployee.role === CONST.POLICY.ROLE.AUDITOR;
let roleBadge = null;
if (isOwner || isAdmin) {
roleBadge = ;
+ } else if (isAuditor) {
+ roleBadge = ;
}
result.push({
@@ -450,7 +454,7 @@ function WorkspaceMembersPage({personalDetails, route, policy, currentUserPerson
return {header};
};
- const changeUserRole = (role: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER) => {
+ const changeUserRole = (role: ValueOf) => {
if (!isEmptyObject(errors)) {
return;
}
@@ -482,23 +486,43 @@ function WorkspaceMembersPage({personalDetails, route, policy, currentUserPerson
const email = personalDetails?.[accountID]?.login ?? '';
return policy?.employeeList?.[email]?.role;
});
- if (selectedEmployeesRoles.find((role) => role === CONST.POLICY.ROLE.ADMIN)) {
- options.push({
- text: translate('workspace.people.makeMember'),
- value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER,
- icon: Expensicons.User,
- onSelected: () => changeUserRole(CONST.POLICY.ROLE.USER),
- });
+
+ const memberOption = {
+ text: translate('workspace.people.makeMember'),
+ value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_MEMBER,
+ icon: Expensicons.User,
+ onSelected: () => changeUserRole(CONST.POLICY.ROLE.USER),
+ };
+ const adminOption = {
+ text: translate('workspace.people.makeAdmin'),
+ value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN,
+ icon: Expensicons.MakeAdmin,
+ onSelected: () => changeUserRole(CONST.POLICY.ROLE.ADMIN),
+ };
+
+ const auditorOption = {
+ text: translate('workspace.people.makeAuditor'),
+ value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_AUDITOR,
+ icon: Expensicons.UserEye,
+ onSelected: () => changeUserRole(CONST.POLICY.ROLE.AUDITOR),
+ };
+
+ const hasAtLeastOneNonAuditorRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.AUDITOR);
+ const hasAtLeastOneNonMemberRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.USER);
+ const hasAtLeastOneNonAdminRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.ADMIN);
+
+ if (hasAtLeastOneNonMemberRole) {
+ options.push(memberOption);
}
- if (selectedEmployeesRoles.find((role) => role === CONST.POLICY.ROLE.USER)) {
- options.push({
- text: translate('workspace.people.makeAdmin'),
- value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_ADMIN,
- icon: Expensicons.MakeAdmin,
- onSelected: () => changeUserRole(CONST.POLICY.ROLE.ADMIN),
- });
+ if (hasAtLeastOneNonAdminRole) {
+ options.push(adminOption);
}
+
+ if (hasAtLeastOneNonAuditorRole) {
+ options.push(auditorOption);
+ }
+
return options;
};
diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx
index 892d38aac48d..a262b747b2bf 100644
--- a/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx
+++ b/src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx
@@ -101,15 +101,24 @@ function WorkspaceMemberDetailsPage({personalDetails, policy, route}: WorkspaceM
{
value: CONST.POLICY.ROLE.ADMIN,
text: translate('common.admin'),
+ alternateText: translate('workspace.common.adminAlternateText'),
isSelected: member?.role === CONST.POLICY.ROLE.ADMIN,
keyForList: CONST.POLICY.ROLE.ADMIN,
},
{
value: CONST.POLICY.ROLE.USER,
text: translate('common.member'),
- isSelected: member?.role !== CONST.POLICY.ROLE.ADMIN,
+ alternateText: translate('workspace.common.memberAlternateText'),
+ isSelected: member?.role === CONST.POLICY.ROLE.USER,
keyForList: CONST.POLICY.ROLE.USER,
},
+ {
+ value: CONST.POLICY.ROLE.AUDITOR,
+ text: translate('common.auditor'),
+ alternateText: translate('workspace.common.auditorAlternateText'),
+ isSelected: member?.role === CONST.POLICY.ROLE.AUDITOR,
+ keyForList: CONST.POLICY.ROLE.AUDITOR,
+ },
],
[member?.role, translate],
);
@@ -247,7 +256,7 @@ function WorkspaceMemberDetailsPage({personalDetails, policy, route}: WorkspaceM
;
text: string;
+ alternateText: string;
isSelected: boolean;
- keyForList: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER;
+ keyForList: ValueOf;
};
type WorkspaceMemberDetailsPageProps = {
@@ -56,6 +58,7 @@ function WorkspaceMemberDetailsRoleSelectionModal({isVisible, items, onRoleChang
sections={[{data: items}]}
ListItem={RadioListItem}
onSelectRow={onRoleChange}
+ isAlternateTextMultilineSupported
shouldSingleExecuteRowSelect
initiallyFocusedOptionKey={items.find((item) => item.isSelected)?.keyForList}
/>