Skip to content
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 possibility to leave from workspaces and workspace expense chats #35671

Merged
merged 53 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
107f84c
implement isPolicyOwner
rezkiy37 Feb 2, 2024
4111039
implement isReportOwner
rezkiy37 Feb 2, 2024
52b16ce
implement draft types for leave API
rezkiy37 Feb 2, 2024
5788e86
implement draft for leave API
rezkiy37 Feb 2, 2024
2114adb
implement draft for leave a workspace chat
rezkiy37 Feb 2, 2024
eb62992
implement draft for leave a workspace
rezkiy37 Feb 2, 2024
3775ad0
integrate draft api data
rezkiy37 Feb 2, 2024
cf3b66e
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Feb 5, 2024
95b8741
use real api for leaving workspaces
rezkiy37 Feb 5, 2024
af8c733
Revert "integrate draft api data"
rezkiy37 Feb 5, 2024
8a3473f
minor fix
rezkiy37 Feb 5, 2024
d27f6e4
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Feb 6, 2024
0ce1db1
move button to top
rezkiy37 Feb 6, 2024
9fde01e
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Feb 7, 2024
a8b9da5
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Feb 12, 2024
184a6cd
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Mar 15, 2024
eb6d577
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Mar 25, 2024
8ddf9be
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Mar 26, 2024
ea03623
integrate leave policy command
rezkiy37 Mar 26, 2024
d850c85
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Mar 27, 2024
5ca68a6
Add leave policy change log const
rezkiy37 Mar 27, 2024
f40cedd
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Mar 29, 2024
f8c8395
Revert "Add leave policy change log const"
rezkiy37 Mar 29, 2024
80caecd
integrate leave policy function
rezkiy37 Mar 29, 2024
ceff5e2
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 2, 2024
1dc5932
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 3, 2024
44bcc09
add comments & use allPolicies
rezkiy37 Apr 3, 2024
4b48baf
add comments & create canLeavePolicyExpenseChat
rezkiy37 Apr 3, 2024
fb038eb
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 4, 2024
9e9f7bf
integrate getAllWorkspaceReports
rezkiy37 Apr 4, 2024
6aa6b13
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 4, 2024
d40d9ff
prettify
rezkiy37 Apr 4, 2024
5c192b8
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 5, 2024
c55cd13
fix ts
rezkiy37 Apr 5, 2024
92fe2a5
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 5, 2024
2b955b3
fix ts
rezkiy37 Apr 5, 2024
24f3740
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 8, 2024
2c2ae9f
check if expense chat
rezkiy37 Apr 8, 2024
9a48ebb
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 9, 2024
858a872
fix finding a chat by participants
rezkiy37 Apr 9, 2024
0b12883
check if the user should leave a chat
rezkiy37 Apr 9, 2024
4de342a
integrate clearReportNotFoundErrors
rezkiy37 Apr 9, 2024
0f9a909
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 10, 2024
e63bb9e
add left a workspace action
rezkiy37 Apr 10, 2024
6b2efac
use separate useEffect
rezkiy37 Apr 10, 2024
8ab074e
show in sidebar
rezkiy37 Apr 10, 2024
223d3ff
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 11, 2024
97cab94
omit authToken
rezkiy37 Apr 11, 2024
5313900
leave a nested report
rezkiy37 Apr 11, 2024
7db78ee
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 12, 2024
b028a6f
fix spanish string
rezkiy37 Apr 12, 2024
d07e04a
Merge branch 'main' of https://github.com/rezkiy37/Expensify into fea…
rezkiy37 Apr 15, 2024
7321ad2
address comments
rezkiy37 Apr 15, 2024
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
6 changes: 6 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ const isFreeGroupPolicy = (policy: OnyxEntry<Policy> | EmptyObject): boolean =>

const isPolicyMember = (policyID: string, policies: OnyxCollection<Policy>): boolean => Object.values(policies ?? {}).some((policy) => policy?.id === policyID);

/**
* Checks if the current user is an owner (creator) of the policy.
*/
const isPolicyOwner = (policy: OnyxEntry<Policy>, currentUserAccountID: number): boolean => policy?.ownerAccountID === currentUserAccountID;

/**
* Create an object mapping member emails to their accountIDs. Filter for members without errors, and get the login email from the personalDetail object using the accountID.
*
Expand Down Expand Up @@ -322,6 +327,7 @@ export {
getCountOfEnabledTagsOfList,
isPendingDeletePolicy,
isPolicyMember,
isPolicyOwner,
isPaidGroupPolicy,
extractPolicyIDFromPath,
getPathWithoutPolicyID,
Expand Down
5 changes: 5 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5456,6 +5456,10 @@ function canBeAutoReimbursed(report: OnyxEntry<Report>, policy: OnyxEntry<Policy
return isAutoReimbursable;
}

function isReportOwner(report: OnyxEntry<Report>): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment for this function.

return report?.ownerAccountID === currentUserPersonalDetails?.accountID;
}

function isAllowedToApproveExpenseReport(report: OnyxEntry<Report>, approverAccountID?: number): boolean {
const policy = getPolicy(report?.policyID);
const {preventSelfApproval} = policy;
Expand Down Expand Up @@ -5717,6 +5721,7 @@ export {
hasUpdatedTotal,
isReportFieldDisabled,
getAvailableReportFields,
isReportOwner,
getReportFieldKey,
reportFieldsEnabled,
getAllAncestorReportActionIDs,
Expand Down
38 changes: 35 additions & 3 deletions src/libs/actions/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ function clearWorkspaceReimbursementErrors(policyID: string) {
/**
* Build optimistic data for removing users from the announcement room
*/
function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: number[]): AnnounceRoomMembersOnyxData {
function removeOptimisticAnnounceRoomMembers(policyID: string, policyName: string, accountIDs: number[]): AnnounceRoomMembersOnyxData {
const announceReport = ReportUtils.getRoom(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID);
const announceRoomMembers: AnnounceRoomMembersOnyxData = {
onyxOptimisticData: [],
Expand All @@ -768,16 +768,31 @@ function removeOptimisticAnnounceRoomMembers(policyID: string, accountIDs: numbe
participantAccountIDs: [...remainUsers],
visibleChatMemberAccountIDs: [...remainUsers],
pendingChatMembers,
...(accountIDs.includes(sessionAccountID)
? {
statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
oldPolicyName: policyName,
hasDraft: false,
}
: {}),
},
});

announceRoomMembers.onyxFailureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${announceReport.reportID}`,
value: {
participantAccountIDs: announceReport.participantAccountIDs,
visibleChatMemberAccountIDs: announceReport.visibleChatMemberAccountIDs,
pendingChatMembers: announceReport?.pendingChatMembers ?? null,
...(accountIDs.includes(sessionAccountID)
? {
statusNum: announceReport.statusNum,
stateNum: announceReport.stateNum,
oldPolicyName: announceReport.oldPolicyName,
hasDraft: announceReport.hasDraft,
}
: {}),
},
});
announceRoomMembers.onyxSuccessData.push({
Expand Down Expand Up @@ -808,7 +823,7 @@ function removeMembers(accountIDs: number[], policyID: string) {
const workspaceChats = ReportUtils.getWorkspaceChats(policyID, accountIDs);
const optimisticClosedReportActions = workspaceChats.map(() => ReportUtils.buildOptimisticClosedReportAction(sessionEmail, policy.name, CONST.REPORT.ARCHIVE_REASON.REMOVED_FROM_POLICY));

const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policyID, accountIDs);
const announceRoomMembers = removeOptimisticAnnounceRoomMembers(policy.id, policy.name, accountIDs);

const optimisticMembersState: OnyxCollection<PolicyMember> = {};
const successMembersState: OnyxCollection<PolicyMember> = {};
Expand Down Expand Up @@ -931,6 +946,23 @@ function removeMembers(accountIDs: number[], policyID: string) {
});
});

if (accountIDs.includes(sessionAccountID)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
},
});
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingAction: policy.pendingAction,
},
});
}

const params: DeleteMembersFromWorkspaceParams = {
emailList: accountIDs.map((accountID) => allPersonalDetails?.[accountID]?.login).join(','),
policyID,
Expand Down
7 changes: 5 additions & 2 deletions src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {ReportWithoutHasDraft} from '@libs/OnyxSelectors/reportWithoutHasDraftSelector';
import reportWithoutHasDraftSelector from '@libs/OnyxSelectors/reportWithoutHasDraftSelector';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as Link from '@userActions/Link';
Expand Down Expand Up @@ -98,6 +99,8 @@ function HeaderView({report, personalDetails, parentReport, parentReportAction,
const isUserCreatedPolicyRoom = ReportUtils.isUserCreatedPolicyRoom(report);
const isPolicyMember = useMemo(() => !isEmptyObject(policy), [policy]);
const canLeaveRoom = ReportUtils.canLeaveRoom(report, isPolicyMember);
const canLeavePolicyExpenseChat =
isPolicyExpenseChat && !(PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPolicyOwner(policy, session?.accountID ?? -1) || ReportUtils.isReportOwner(report));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a utility function for this in ReportUtils

const reportDescription = ReportUtils.getReportDescriptionText(report);
const policyName = ReportUtils.getPolicyName(report, true);
const policyDescription = ReportUtils.getPolicyDescriptionText(policy);
Expand Down Expand Up @@ -144,9 +147,9 @@ function HeaderView({report, personalDetails, parentReport, parentReportAction,
Report.updateNotificationPreference(reportID, report.notificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, false, report.parentReportID, report.parentReportActionID),
);

const canJoinOrLeave = !isSelfDM && (isChatThread || isUserCreatedPolicyRoom || canLeaveRoom);
const canJoinOrLeave = !isSelfDM && (isChatThread || isUserCreatedPolicyRoom || canLeaveRoom || canLeavePolicyExpenseChat);
const canJoin = canJoinOrLeave && !isWhisperAction && report.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const canLeave = canJoinOrLeave && ((isChatThread && !!report.notificationPreference?.length) || isUserCreatedPolicyRoom || canLeaveRoom);
const canLeave = canJoinOrLeave && ((isChatThread && !!report.notificationPreference?.length) || isUserCreatedPolicyRoom || canLeaveRoom || canLeavePolicyExpenseChat);
if (canJoin) {
threeDotMenuItems.push({
icon: Expensicons.ChatBubbles,
Expand Down
22 changes: 19 additions & 3 deletions src/pages/workspace/WorkspacesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import * as ReportUtils from '@libs/ReportUtils';
import type {AvatarSource} from '@libs/UserUtils';
import * as App from '@userActions/App';
import * as Policy from '@userActions/Policy';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {PolicyMembers, Policy as PolicyType, ReimbursementAccount, Report} from '@src/types/onyx';
import type {PolicyMembers, Policy as PolicyType, ReimbursementAccount, Report, Session as SessionType} from '@src/types/onyx';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading';
Expand Down Expand Up @@ -79,6 +80,9 @@ type WorkspaceListPageOnyxProps = {

/** All reports shared with the user (coming from Onyx) */
reports: OnyxCollection<Report>;

/** Session info for the currently logged in user. */
session: OnyxEntry<SessionType>;
};

type WorkspaceListPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceListPageOnyxProps;
Expand Down Expand Up @@ -114,7 +118,7 @@ function dismissWorkspaceError(policyID: string, pendingAction: OnyxCommon.Pendi
throw new Error('Not implemented');
}

function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, reports}: WorkspaceListPageProps) {
function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, reports, session}: WorkspaceListPageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand Down Expand Up @@ -148,6 +152,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r
const getMenuItem = useCallback(
({item, index}: GetMenuItem) => {
const isAdmin = item.role === CONST.POLICY.ROLE.ADMIN;
const isOwner = item.ownerAccountID === session?.accountID;
// Menu options to navigate to the chat report of #admins and #announce room.
// For navigation, the chat report ids may be unavailable due to the missing chat reports in Onyx.
// In such cases, let us use the available chat report ids from the policy.
Expand All @@ -165,6 +170,14 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r
});
}

if (!(isAdmin || isOwner)) {
threeDotsMenuItems.push({
icon: Expensicons.ChatBubbles,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋 coming from #46248.

Pretty minor issue and part of the polish issue. We should be using the Exit icon.

text: translate('common.leave'),
onSelected: Session.checkIfActionIsAllowed(() => Policy.removeMembers([session?.accountID ?? 0], item.policyID ?? '')),
rezkiy37 marked this conversation as resolved.
Show resolved Hide resolved
});
}

if (isAdmin && item.adminRoom) {
threeDotsMenuItems.push({
icon: Expensicons.Hashtag,
Expand Down Expand Up @@ -214,7 +227,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, r
</PressableWithoutFeedback>
);
},
[isLessThanMediumScreen, styles.mb3, styles.mh5, styles.ph5, styles.hoveredComponentBG, translate],
[session?.accountID, styles.mh5, styles.mb3, styles.ph5, styles.hoveredComponentBG, translate, isLessThanMediumScreen],
);

const listHeaderComponent = useCallback(() => {
Expand Down Expand Up @@ -444,5 +457,8 @@ export default withPolicyAndFullscreenLoading(
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
session: {
key: ONYXKEYS.SESSION,
},
})(WorkspacesListPage),
);
Loading