From d743ebbede7c32ab2d1fcde7ff07aac14a83ac35 Mon Sep 17 00:00:00 2001 From: Jasper Huang Date: Tue, 7 Mar 2023 10:08:22 -0800 Subject: [PATCH] Merge pull request #15392 from Expensify/marco-addLeaveRoomAction Add leaveRoom action (cherry picked from commit 17cf77e9c9c00c88e824c89de6374683951b8d4f) --- src/CONST.js | 4 ++- src/languages/en.js | 3 ++ src/languages/es.js | 3 ++ src/libs/ReportUtils.js | 32 +++++++++++++++++++ src/libs/actions/Policy.js | 34 +++++++++++++++++++++ src/pages/ReportDetailsPage.js | 12 ++++++-- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- 7 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 203ab6a09255..b8c26f163376 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -352,8 +352,10 @@ const CONST = { ALWAYS: 'always', }, VISIBILITY: { - RESTRICTED: 'restricted', + PUBLIC: 'public', + PUBLIC_ANNOUNCE: 'public_announce', PRIVATE: 'private', + RESTRICTED: 'restricted', }, RESERVED_ROOM_NAMES: ['#admins', '#announce'], MAX_PREVIEW_AVATARS: 4, diff --git a/src/languages/en.js b/src/languages/en.js index 7d76503bd399..0e5afed9a424 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -1113,6 +1113,7 @@ export default { visibility: 'Visibility', restrictedDescription: 'People in your workspace can find this room', privateDescription: 'People invited to this room can find it', + publicDescription: 'Anyone can find it', createRoom: 'Create room', roomAlreadyExistsError: 'A room with this name already exists', roomNameReservedError: 'A room on this workspace already uses this name', @@ -1126,6 +1127,8 @@ export default { visibilityOptions: { restricted: 'Restricted', private: 'Private', + public: 'Public', + public_announce: 'Public Announce', }, }, statementPage: { diff --git a/src/languages/es.js b/src/languages/es.js index a1f08793056a..f282242cecac 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -1115,6 +1115,7 @@ export default { visibility: 'Visibilidad', restrictedDescription: 'Sólo las personas en tu espacio de trabajo pueden encontrar esta sala', privateDescription: 'Sólo las personas que están invitadas a esta sala pueden encontrarla', + publicDescription: 'Cualquiera puede encontrarlo', createRoom: 'Crea una sala de chat', roomAlreadyExistsError: 'Ya existe una sala con este nombre', roomNameReservedError: 'Una sala en este espacio de trabajo ya usa este nombre', @@ -1128,6 +1129,8 @@ export default { visibilityOptions: { restricted: 'Restringida', private: 'Privada', + public: 'Público', + public_announce: 'Anuncio Público', }, }, statementPage: { diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 83a84f7be041..7e0b6039eb41 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -1587,12 +1587,44 @@ function getIOUOptions(report, reportParticipants, betas) { ]; } +/** + * Allows a user to leave a policy room according to the following conditions of the visibility or chatType rNVP: + * `public` - Anyone can leave (because anybody can join) + * `public_announce` - Only non-policy members can leave (it's auto-shared with policy members) + * `policy_admins` - Nobody can leave (it's auto-shared with all policy admins) + * `policy_announce` - Nobody can leave (it's auto-shared with all policy members) + * `policy` - Anyone can leave (though only policy members can join) + * `domain` - Nobody can leave (it's auto-shared with domain members) + * `dm` - Nobody can leave (it's auto-shared with users) + * `private` - Anybody can leave (though you can only be invited to join) + * + * @param {Object} report + * @param {String} report.visibility + * @param {String} report.chatType + * @param {Boolean} isPolicyMember + * @returns {Boolean} + */ +function canLeaveRoom(report, isPolicyMember) { + if (_.isEmpty(report.visibility)) { + if (report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS + || report.chatType === CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE + || report.chatType === CONST.REPORT.CHAT_TYPE.DOMAIN_ALL + || _.isEmpty(report.chatType)) { // DM chats don't have a chatType + return false; + } + } else if (report.visibility === CONST.REPORT.VISIBILITY.PUBLIC_ANNOUNCE && isPolicyMember) { + return false; + } + return true; +} + export { getReportParticipantsTitle, isReportMessageAttachment, findLastAccessedReport, canEditReportAction, canDeleteReportAction, + canLeaveRoom, sortReportsByLastRead, isDefaultRoom, isAdminRoom, diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index c269accf6ae1..86a587ed448c 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -14,6 +14,7 @@ import * as OptionsListUtils from '../OptionsListUtils'; import DateUtils from '../DateUtils'; import * as ReportUtils from '../ReportUtils'; import Log from '../Log'; +import * as Report from './Report'; const allPolicies = {}; Onyx.connect({ @@ -1000,6 +1001,38 @@ function openWorkspaceInvitePage(policyID, clientMemberEmails) { }); } +/** + * + * @param {String} reportID + */ +function leaveRoom(reportID) { + API.write('LeaveRoom', { + reportID, + }, { + optimisticData: [ + { + onyxMethod: CONST.ONYX.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, + statusNum: CONST.REPORT.STATUS.CLOSED, + }, + }, + ], + failureData: [ + { + onyxMethod: CONST.ONYX.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + stateNum: CONST.REPORT.STATE_NUM.OPEN, + statusNum: CONST.REPORT.STATUS.OPEN, + }, + }, + ], + }); + Report.navigateToConciergeChat(); +} + export { removeMembers, addMembersToWorkspace, @@ -1027,4 +1060,5 @@ export { openWorkspaceMembersPage, openWorkspaceInvitePage, removeWorkspace, + leaveRoom, }; diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index 02bd202c1d2c..5089b87c2742 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -15,6 +15,7 @@ import styles from '../styles/styles'; import DisplayNames from '../components/DisplayNames'; import * as OptionsListUtils from '../libs/OptionsListUtils'; import * as ReportUtils from '../libs/ReportUtils'; +import * as Policy from '../libs/actions/Policy'; import participantPropTypes from '../components/participantPropTypes'; import * as Expensicons from '../components/Icon/Expensicons'; import ROUTES from '../ROUTES'; @@ -86,14 +87,19 @@ class ReportDetailsPage extends Component { translationKey: 'common.invite', icon: Expensicons.Plus, action: () => { /* Placeholder for when inviting other users is built in */ }, - }, - { + }); + } + + const policy = this.props.policies[`${ONYXKEYS.COLLECTION.POLICY}${this.props.report.policyID}`]; + if (ReportUtils.isUserCreatedPolicyRoom(this.props.report) || ReportUtils.canLeaveRoom(this.props.report, !_.isEmpty(policy))) { + menuItems.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.LEAVE_ROOM, translationKey: 'common.leaveRoom', icon: Expensicons.Exit, - action: () => { /* Placeholder for when leaving rooms is built in */ }, + action: () => Policy.leaveRoom(this.props.report.reportID), }); } + return menuItems; } diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 0cc96e7ce33a..4db4670ac63e 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -117,7 +117,7 @@ class WorkspaceNewRoomPage extends React.Component { policy => ({label: policy.name, key: policy.id, value: policy.id}), ); - const visibilityOptions = _.map(_.values(CONST.REPORT.VISIBILITY), visibilityOption => ({ + const visibilityOptions = _.map(_.filter(_.values(CONST.REPORT.VISIBILITY), visibilityOption => visibilityOption !== CONST.REPORT.VISIBILITY.PUBLIC_ANNOUNCE), visibilityOption => ({ label: this.props.translate(`newRoomPage.visibilityOptions.${visibilityOption}`), value: visibilityOption, description: this.props.translate(`newRoomPage.${visibilityOption}Description`),