Skip to content

Commit 0e2f742

Browse files
authored
Merge pull request #21950 from rezkiy37/feature/21456-polish-admin-rooms
Polish admins-only policy room feature
2 parents beebb67 + b886d07 commit 0e2f742

File tree

7 files changed

+100
-7
lines changed

7 files changed

+100
-7
lines changed

src/components/Form.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ function Form(props) {
209209
* @returns {React.Component}
210210
*/
211211
const childrenWrapperWithProps = useCallback(
212-
(childNodes) =>
213-
React.Children.map(childNodes, (child) => {
212+
(childNodes) => {
213+
const childrenElements = React.Children.map(childNodes, (child) => {
214214
// Just render the child if it is not a valid React element, e.g. text within a <Text> component
215215
if (!React.isValidElement(child)) {
216216
return child;
@@ -330,7 +330,28 @@ function Form(props) {
330330
}
331331
},
332332
});
333-
}),
333+
});
334+
335+
// We need to verify that all references and values are still actual.
336+
// We should not store it when e.g. some input has been unmounted
337+
_.each(inputRefs.current, (inputRef, inputID) => {
338+
if (inputRef) {
339+
return;
340+
}
341+
342+
delete inputRefs.current[inputID];
343+
344+
setInputValues((prevState) => {
345+
const copyPrevState = _.clone(prevState);
346+
347+
delete copyPrevState[inputID];
348+
349+
return copyPrevState;
350+
});
351+
});
352+
353+
return childrenElements;
354+
},
334355
[errors, inputRefs, inputValues, onValidate, props.draftValues, props.formID, props.formState, setTouchedInput],
335356
);
336357

src/languages/en.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ export default {
288288
beginningOfChatHistoryDomainRoomPartTwo: ' to chat with colleagues, share tips, and ask questions.',
289289
beginningOfChatHistoryAdminRoomPartOne: ({workspaceName}) => `Collaboration among ${workspaceName} admins starts here! 🎉\nUse `,
290290
beginningOfChatHistoryAdminRoomPartTwo: ' to chat about topics such as workspace configurations and more.',
291+
beginningOfChatHistoryAdminOnlyPostingRoomPartOne: 'Use ',
292+
beginningOfChatHistoryAdminOnlyPostingRoomPartTwo: ({workspaceName}) => ` to hear about important announcements related to ${workspaceName}`,
291293
beginningOfChatHistoryAnnounceRoomPartOne: ({workspaceName}) => `Collaboration between all ${workspaceName} members starts here! 🎉\nUse `,
292294
beginningOfChatHistoryAnnounceRoomPartTwo: ({workspaceName}) => ` to chat about anything ${workspaceName} related.`,
293295
beginningOfChatHistoryUserRoomPartOne: 'Collaboration starts here! 🎉\nUse this space to chat about anything ',

src/languages/es.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ export default {
287287
beginningOfChatHistoryDomainRoomPartTwo: ' para chatear con compañeros, compartir consejos o hacer una pregunta.',
288288
beginningOfChatHistoryAdminRoomPartOne: ({workspaceName}) => `Este es el lugar para que los administradores de ${workspaceName} colaboren! 🎉\nUsa `,
289289
beginningOfChatHistoryAdminRoomPartTwo: ' para chatear sobre temas como la configuración del espacio de trabajo y mas.',
290+
beginningOfChatHistoryAdminOnlyPostingRoomPartOne: 'Utiliza ',
291+
beginningOfChatHistoryAdminOnlyPostingRoomPartTwo: ({workspaceName}) => ` para enterarte de anuncios importantes relacionados con ${workspaceName}`,
290292
beginningOfChatHistoryAnnounceRoomPartOne: ({workspaceName}) => `Este es el lugar para que todos los miembros de ${workspaceName} colaboren! 🎉\nUsa `,
291293
beginningOfChatHistoryAnnounceRoomPartTwo: ({workspaceName}) => ` para chatear sobre cualquier cosa relacionada con ${workspaceName}.`,
292294
beginningOfChatHistoryUserRoomPartOne: 'Este es el lugar para colaborar! 🎉\nUsa este espacio para chatear sobre cualquier cosa relacionada con ',

src/libs/ReportUtils.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,16 @@ function isAdminRoom(report) {
274274
return getChatType(report) === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS;
275275
}
276276

277+
/**
278+
* Whether the provided report is an Admin-only posting room
279+
* @param {Object} report
280+
* @param {String} report.writeCapability
281+
* @returns {Boolean}
282+
*/
283+
function isAdminsOnlyPostingRoom(report) {
284+
return lodashGet(report, 'writeCapability', CONST.REPORT.WRITE_CAPABILITIES.ALL) === CONST.REPORT.WRITE_CAPABILITIES.ADMINS;
285+
}
286+
277287
/**
278288
* Whether the provided report is a Announce room
279289
* @param {Object} report
@@ -567,6 +577,18 @@ function isPolicyExpenseChatAdmin(report, policies) {
567577
return policyRole === CONST.POLICY.ROLE.ADMIN;
568578
}
569579

580+
/**
581+
* Checks if the current user is the admin of the policy.
582+
* @param {String} policyID
583+
* @param {Object} policies must have OnyxKey prefix (i.e 'policy_') for keys
584+
* @returns {Boolean}
585+
*/
586+
function isPolicyAdmin(policyID, policies) {
587+
const policyRole = lodashGet(policies, [`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, 'role']);
588+
589+
return policyRole === CONST.POLICY.ROLE.ADMIN;
590+
}
591+
570592
/**
571593
* Returns true if report is a DM/Group DM chat.
572594
*
@@ -663,6 +685,9 @@ function getRoomWelcomeMessage(report) {
663685
} else if (isAdminRoom(report)) {
664686
welcomeMessage.phrase1 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAdminRoomPartOne', {workspaceName});
665687
welcomeMessage.phrase2 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAdminRoomPartTwo');
688+
} else if (isAdminsOnlyPostingRoom(report)) {
689+
welcomeMessage.phrase1 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAdminOnlyPostingRoomPartOne');
690+
welcomeMessage.phrase2 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAdminOnlyPostingRoomPartTwo', {workspaceName});
666691
} else if (isAnnounceRoom(report)) {
667692
welcomeMessage.phrase1 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAnnounceRoomPartOne', {workspaceName});
668693
welcomeMessage.phrase2 = Localize.translateLocal('reportActionsView.beginningOfChatHistoryAnnounceRoomPartTwo', {workspaceName});
@@ -1730,6 +1755,7 @@ function buildOptimisticTaskReportAction(taskReportID, actionName, message = '')
17301755
* @param {Boolean} isOwnPolicyExpenseChat
17311756
* @param {String} oldPolicyName
17321757
* @param {String} visibility
1758+
* @param {String} writeCapability
17331759
* @param {String} notificationPreference
17341760
* @param {String} parentReportActionID
17351761
* @param {String} parentReportID
@@ -1744,6 +1770,7 @@ function buildOptimisticChatReport(
17441770
isOwnPolicyExpenseChat = false,
17451771
oldPolicyName = '',
17461772
visibility = undefined,
1773+
writeCapability = CONST.REPORT.WRITE_CAPABILITIES.ALL,
17471774
notificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS,
17481775
parentReportActionID = '',
17491776
parentReportID = '',
@@ -1774,6 +1801,7 @@ function buildOptimisticChatReport(
17741801
statusNum: 0,
17751802
visibility,
17761803
welcomeMessage: '',
1804+
writeCapability,
17771805
};
17781806
}
17791807

@@ -2653,6 +2681,7 @@ export {
26532681
getPolicyType,
26542682
isArchivedRoom,
26552683
isPolicyExpenseChatAdmin,
2684+
isPolicyAdmin,
26562685
isPublicRoom,
26572686
isPublicAnnounceRoom,
26582687
isConciergeChatReport,

src/libs/actions/Report.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,8 +1264,9 @@ function navigateToConciergeChat() {
12641264
* @param {String} reportName
12651265
* @param {String} visibility
12661266
* @param {Array<Number>} policyMembersAccountIDs
1267+
* @param {String} writeCapability
12671268
*/
1268-
function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs) {
1269+
function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs, writeCapability) {
12691270
// The participants include the current user (admin), and for restricted rooms, the policy members. Participants must not be empty.
12701271
const members = visibility === CONST.REPORT.VISIBILITY.RESTRICTED ? policyMembersAccountIDs : [];
12711272
const participants = _.unique([currentUserAccountID, ...members]);
@@ -1278,6 +1279,7 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI
12781279
false,
12791280
'',
12801281
visibility,
1282+
writeCapability,
12811283

12821284
// The room might contain all policy members so notifying always should be opt-in only.
12831285
CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY,
@@ -1344,6 +1346,7 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI
13441346
visibility,
13451347
reportID: policyReport.reportID,
13461348
createdReportActionID: createdReportAction.reportActionID,
1349+
writeCapability,
13471350
},
13481351
{optimisticData, successData, failureData},
13491352
);

src/pages/home/report/ReportActionsList.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
22
import React, {useCallback, useEffect, useState} from 'react';
33
import Animated, {useSharedValue, useAnimatedStyle, withTiming} from 'react-native-reanimated';
44
import _ from 'underscore';
5+
import lodashGet from 'lodash/get';
56
import InvertedFlatList from '../../../components/InvertedFlatList';
67
import compose from '../../../libs/compose';
78
import styles from '../../../styles/styles';
@@ -162,14 +163,20 @@ function ReportActionsList(props) {
162163
// To notify there something changes we can use extraData prop to flatlist
163164
const extraData = [props.isSmallScreenWidth ? props.newMarkerReportActionID : undefined, ReportUtils.isArchivedRoom(props.report)];
164165
const shouldShowReportRecipientLocalTime = ReportUtils.canShowReportRecipientLocalTime(props.personalDetailsList, props.report, props.currentUserPersonalDetails.accountID);
166+
167+
const errors = lodashGet(props.report, 'errorFields.addWorkspaceRoom') || lodashGet(props.report, 'errorFields.createChat');
168+
const isArchivedRoom = ReportUtils.isArchivedRoom(props.report);
169+
const hideComposer = ReportUtils.shouldHideComposer(props.report, errors);
170+
const shouldOmitBottomSpace = hideComposer || isArchivedRoom;
171+
165172
return (
166173
<Animated.View style={[animatedStyles, styles.flex1]}>
167174
<InvertedFlatList
168175
accessibilityLabel={props.translate('sidebarScreen.listOfChatMessages')}
169176
ref={reportScrollManager.ref}
170177
data={props.sortedReportActions}
171178
renderItem={renderItem}
172-
contentContainerStyle={[styles.chatContentScrollView, shouldShowReportRecipientLocalTime ? styles.pt0 : {}]}
179+
contentContainerStyle={[styles.chatContentScrollView, shouldShowReportRecipientLocalTime || shouldOmitBottomSpace ? styles.pt0 : {}]}
173180
keyExtractor={keyExtractor}
174181
initialRowHeight={32}
175182
initialNumToRender={calculateInitialNumToRender()}

src/pages/workspace/WorkspaceNewRoomPage.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import Permissions from '../../libs/Permissions';
1818
import Log from '../../libs/Log';
1919
import * as ErrorUtils from '../../libs/ErrorUtils';
2020
import * as ValidationUtils from '../../libs/ValidationUtils';
21+
import * as ReportUtils from '../../libs/ReportUtils';
2122
import * as PolicyUtils from '../../libs/PolicyUtils';
2223
import Form from '../../components/Form';
2324
import shouldDelayFocus from '../../libs/shouldDelayFocus';
@@ -66,14 +67,22 @@ const defaultProps = {
6667
function WorkspaceNewRoomPage(props) {
6768
const {translate} = useLocalize();
6869
const [visibility, setVisibility] = useState(CONST.REPORT.VISIBILITY.RESTRICTED);
70+
const [policyID, setPolicyID] = useState(null);
6971
const visibilityDescription = useMemo(() => translate(`newRoomPage.${visibility}Description`), [translate, visibility]);
72+
const isPolicyAdmin = useMemo(() => {
73+
if (!policyID) {
74+
return false;
75+
}
76+
77+
return ReportUtils.isPolicyAdmin(policyID, props.policies);
78+
}, [policyID, props.policies]);
7079

7180
/**
7281
* @param {Object} values - form input values passed by the Form component
7382
*/
7483
const submit = (values) => {
7584
const policyMembers = _.map(_.keys(props.allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${values.policyID}`]), (accountID) => Number(accountID));
76-
Report.addPolicyReport(values.policyID, values.roomName, values.visibility, policyMembers);
85+
Report.addPolicyReport(values.policyID, values.roomName, values.visibility, policyMembers, values.writeCapability);
7786
};
7887

7988
/**
@@ -109,6 +118,15 @@ function WorkspaceNewRoomPage(props) {
109118

110119
const workspaceOptions = useMemo(() => _.map(PolicyUtils.getActivePolicies(props.policies), (policy) => ({label: policy.name, key: policy.id, value: policy.id})), [props.policies]);
111120

121+
const writeCapabilityOptions = useMemo(
122+
() =>
123+
_.map(CONST.REPORT.WRITE_CAPABILITIES, (value) => ({
124+
value,
125+
label: translate(`writeCapabilityPage.writeCapability.${value}`),
126+
})),
127+
[translate],
128+
);
129+
112130
const visibilityOptions = useMemo(
113131
() =>
114132
_.map(
@@ -156,14 +174,25 @@ function WorkspaceNewRoomPage(props) {
156174
shouldDelayFocus={shouldDelayFocus}
157175
/>
158176
</View>
159-
<View style={styles.mb5}>
177+
<View style={styles.mb2}>
160178
<Picker
161179
inputID="policyID"
162180
label={translate('workspace.common.workspace')}
163181
placeholder={{value: '', label: translate('newRoomPage.selectAWorkspace')}}
164182
items={workspaceOptions}
183+
onValueChange={setPolicyID}
165184
/>
166185
</View>
186+
{isPolicyAdmin && (
187+
<View style={styles.mb2}>
188+
<Picker
189+
inputID="writeCapability"
190+
label={translate('writeCapabilityPage.label')}
191+
items={writeCapabilityOptions}
192+
defaultValue={CONST.REPORT.WRITE_CAPABILITIES.ALL}
193+
/>
194+
</View>
195+
)}
167196
<View style={styles.mb2}>
168197
<Picker
169198
inputID="visibility"

0 commit comments

Comments
 (0)