From 40e752263aa058f558014820d3beeb6c55fc39cd Mon Sep 17 00:00:00 2001 From: Alex D Date: Sat, 1 Jul 2023 14:59:15 +0300 Subject: [PATCH 1/7] Component refactor: WorkspaceNewRoomPage --- src/pages/workspace/WorkspaceNewRoomPage.js | 166 +++++++++----------- 1 file changed, 78 insertions(+), 88 deletions(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 361610266b42..6b0ccc6b90ee 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState,useCallback} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -65,43 +65,34 @@ const defaultProps = { allPolicyMembers: {}, }; -class WorkspaceNewRoomPage extends React.Component { - constructor(props) { - super(props); - - this.state = { - visibilityDescription: this.props.translate('newRoomPage.restrictedDescription'), - }; - - this.validate = this.validate.bind(this); - this.submit = this.submit.bind(this); - this.updateVisibilityDescription = this.updateVisibilityDescription.bind(this); - } +function WorkspaceNewRoomPage(props) { + const [visibilityDescription, setVisibilityDescription] = useState(props.translate('newRoomPage.restrictedDescription')); /** * @param {Object} values - form input values passed by the Form component */ - submit(values) { - const policyMembers = _.map(_.keys(this.props.allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${values.policyID}`]), (accountID) => Number(accountID)); + const submit = (values) => { + const policyMembers = _.map(_.keys(props.allPolicyMembers[`${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${values.policyID}`]), (accountID) => Number(accountID)); Report.addPolicyReport(values.policyID, values.roomName, values.visibility, policyMembers); - } + }; /** * @param {String} visibility - form input value passed by the Form component */ - updateVisibilityDescription(visibility) { - const visibilityDescription = this.props.translate(`newRoomPage.${visibility}Description`); - if (visibilityDescription === this.state.visibilityDescription) { + const updateVisibilityDescription = useCallback((visibility) => { + const newVisibilityDescription = props.translate(`newRoomPage.${visibility}Description`); + if (newVisibilityDescription === visibilityDescription) { return; } - this.setState({visibilityDescription}); - } + setVisibilityDescription({newVisibilityDescription}); + // eslint-disable-next-line react-hooks/exhaustive-deps + },[visibilityDescription]); /** * @param {Object} values - form input values passed by the Form component * @returns {Boolean} */ - validate(values) { + const validate = useCallback((values) => { const errors = {}; if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { @@ -113,7 +104,7 @@ class WorkspaceNewRoomPage extends React.Component { } else if (ValidationUtils.isReservedRoomName(values.roomName)) { // Certain names are reserved for default rooms and should not be used for policy rooms. ErrorUtils.addErrorMessage(errors, 'roomName', ['newRoomPage.roomNameReservedError', {reservedName: values.roomName}]); - } else if (ValidationUtils.isExistingRoomName(values.roomName, this.props.reports, values.policyID)) { + } else if (ValidationUtils.isExistingRoomName(values.roomName, props.reports, values.policyID)) { // Certain names are reserved for default rooms and should not be used for policy rooms. ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); } @@ -123,78 +114,77 @@ class WorkspaceNewRoomPage extends React.Component { } return errors; - } + },[props.reports]); - render() { - if (!Permissions.canUsePolicyRooms(this.props.betas)) { - Log.info('Not showing create Policy Room page since user is not on policy rooms beta'); - Navigation.dismissModal(); - return null; - } + if (!Permissions.canUsePolicyRooms(props.betas)) { + Log.info('Not showing create Policy Room page since user is not on policy rooms beta'); + Navigation.dismissModal(); + return null; + } - // Workspaces are policies with type === 'free' - const workspaceOptions = _.map( - _.filter(this.props.policies, (policy) => policy && policy.type === CONST.POLICY.TYPE.FREE), - (policy) => ({label: policy.name, key: policy.id, value: policy.id}), - ); - - 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`), - }), - ); - - return ( - policy && policy.type === CONST.POLICY.TYPE.FREE), + (policy) => ({label: policy.name, key: policy.id, value: policy.id}), + ); + + const visibilityOptions = _.map( + _.filter(_.values(CONST.REPORT.VISIBILITY), (visibilityOption) => visibilityOption !== CONST.REPORT.VISIBILITY.PUBLIC_ANNOUNCE), + (visibilityOption) => ({ + label: props.translate(`newRoomPage.visibilityOptions.${visibilityOption}`), + value: visibilityOption, + description: props.translate(`newRoomPage.${visibilityOption}Description`), + }), + ); + + return ( + + +
- - - - - - - - - - - - {this.state.visibilityDescription} - -
- ); - } + + + + + + + + + + {visibilityDescription} + +
+ ); } WorkspaceNewRoomPage.propTypes = propTypes; WorkspaceNewRoomPage.defaultProps = defaultProps; +WorkspaceNewRoomPage.displayName = 'WorkspaceNewRoomPage'; export default compose( withOnyx({ From 874ad668e9307f56126608b77811bbbc5bd2d599 Mon Sep 17 00:00:00 2001 From: Alex D Date: Sat, 1 Jul 2023 16:04:09 +0300 Subject: [PATCH 2/7] Fix: changes after prettier run --- src/pages/workspace/WorkspaceNewRoomPage.js | 70 +++++++++++---------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 6b0ccc6b90ee..b69ef0e2b09d 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -1,4 +1,4 @@ -import React, {useState,useCallback} from 'react'; +import React, {useState, useCallback} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -79,42 +79,48 @@ function WorkspaceNewRoomPage(props) { /** * @param {String} visibility - form input value passed by the Form component */ - const updateVisibilityDescription = useCallback((visibility) => { - const newVisibilityDescription = props.translate(`newRoomPage.${visibility}Description`); - if (newVisibilityDescription === visibilityDescription) { - return; - } - setVisibilityDescription({newVisibilityDescription}); - // eslint-disable-next-line react-hooks/exhaustive-deps - },[visibilityDescription]); + const updateVisibilityDescription = useCallback( + (visibility) => { + const newVisibilityDescription = props.translate(`newRoomPage.${visibility}Description`); + if (newVisibilityDescription === visibilityDescription) { + return; + } + setVisibilityDescription({newVisibilityDescription}); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, + [visibilityDescription], + ); /** * @param {Object} values - form input values passed by the Form component * @returns {Boolean} */ - const validate = useCallback((values) => { - const errors = {}; - - if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { - // We error if the user doesn't enter a room name or left blank - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.pleaseEnterRoomName'); - } else if (values.roomName !== CONST.POLICY.ROOM_PREFIX && !ValidationUtils.isValidRoomName(values.roomName)) { - // We error if the room name has invalid characters - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomNameInvalidError'); - } else if (ValidationUtils.isReservedRoomName(values.roomName)) { - // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', ['newRoomPage.roomNameReservedError', {reservedName: values.roomName}]); - } else if (ValidationUtils.isExistingRoomName(values.roomName, props.reports, values.policyID)) { - // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); - } - - if (!values.policyID) { - errors.policyID = 'newRoomPage.pleaseSelectWorkspace'; - } - - return errors; - },[props.reports]); + const validate = useCallback( + (values) => { + const errors = {}; + + if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { + // We error if the user doesn't enter a room name or left blank + ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.pleaseEnterRoomName'); + } else if (values.roomName !== CONST.POLICY.ROOM_PREFIX && !ValidationUtils.isValidRoomName(values.roomName)) { + // We error if the room name has invalid characters + ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomNameInvalidError'); + } else if (ValidationUtils.isReservedRoomName(values.roomName)) { + // Certain names are reserved for default rooms and should not be used for policy rooms. + ErrorUtils.addErrorMessage(errors, 'roomName', ['newRoomPage.roomNameReservedError', {reservedName: values.roomName}]); + } else if (ValidationUtils.isExistingRoomName(values.roomName, props.reports, values.policyID)) { + // Certain names are reserved for default rooms and should not be used for policy rooms. + ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); + } + + if (!values.policyID) { + errors.policyID = 'newRoomPage.pleaseSelectWorkspace'; + } + + return errors; + }, + [props.reports], + ); if (!Permissions.canUsePolicyRooms(props.betas)) { Log.info('Not showing create Policy Room page since user is not on policy rooms beta'); From 8f5236317d9c2db612ce206ce1131a76e70563b2 Mon Sep 17 00:00:00 2001 From: Alex D Date: Sat, 1 Jul 2023 16:32:50 +0300 Subject: [PATCH 3/7] Fix lint issue after prettier run --- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index b69ef0e2b09d..688bbac02495 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -86,8 +86,8 @@ function WorkspaceNewRoomPage(props) { return; } setVisibilityDescription({newVisibilityDescription}); - // eslint-disable-next-line react-hooks/exhaustive-deps }, + // eslint-disable-next-line react-hooks/exhaustive-deps [visibilityDescription], ); From 2d281be897b05e8fe64a91b8294f31919c8b6a3a Mon Sep 17 00:00:00 2001 From: Aleksei Dvoretskii Date: Sun, 2 Jul 2023 13:51:07 -0700 Subject: [PATCH 4/7] Update src/pages/workspace/WorkspaceNewRoomPage.js Co-authored-by: Fedi Rajhi --- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 688bbac02495..3e303e8cb376 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -153,7 +153,7 @@ function WorkspaceNewRoomPage(props) { formID={ONYXKEYS.FORMS.NEW_ROOM_FORM} submitButtonText={props.translate('newRoomPage.createRoom')} scrollContextEnabled - style={[styles.mh5, styles.mt5, styles.flexGrow1]} + style={[styles.mh5, styles.flexGrow1]} validate={validate} onSubmit={submit} enabledWhenOffline From 1aa2452b1c9e47ef12a9947d2a2b9c3f2abb1a38 Mon Sep 17 00:00:00 2001 From: Alex D Date: Mon, 3 Jul 2023 01:08:45 +0300 Subject: [PATCH 5/7] Add useLocalize, useMemo, minor fixes --- src/pages/workspace/WorkspaceNewRoomPage.js | 107 +++++++++----------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 3e303e8cb376..c05430300b76 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -1,11 +1,10 @@ -import React, {useState, useCallback} from 'react'; +import React, {useState, useCallback, useMemo} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import * as Report from '../../libs/actions/Report'; -import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; -import compose from '../../libs/compose'; +import useLocalize from '../../hooks/useLocalize'; import HeaderWithBackButton from '../../components/HeaderWithBackButton'; import Navigation from '../../libs/Navigation/Navigation'; import ScreenWrapper from '../../components/ScreenWrapper'; @@ -55,8 +54,6 @@ const propTypes = { /** A collection of objects for all policies which key policy member objects by accountIDs */ allPolicyMembers: PropTypes.objectOf(PropTypes.objectOf(policyMemberPropType)), - - ...withLocalizePropTypes, }; const defaultProps = { betas: [], @@ -66,7 +63,9 @@ const defaultProps = { }; function WorkspaceNewRoomPage(props) { - const [visibilityDescription, setVisibilityDescription] = useState(props.translate('newRoomPage.restrictedDescription')); + const {translate} = useLocalize(); + const [visibility, setVisibility] = useState(CONST.REPORT.VISIBILITY.RESTRICTED); + const visibilityDescription = useMemo(() => translate(`newRoomPage.${visibility}Description`), [translate, visibility]); /** * @param {Object} values - form input values passed by the Form component @@ -76,21 +75,6 @@ function WorkspaceNewRoomPage(props) { Report.addPolicyReport(values.policyID, values.roomName, values.visibility, policyMembers); }; - /** - * @param {String} visibility - form input value passed by the Form component - */ - const updateVisibilityDescription = useCallback( - (visibility) => { - const newVisibilityDescription = props.translate(`newRoomPage.${visibility}Description`); - if (newVisibilityDescription === visibilityDescription) { - return; - } - setVisibilityDescription({newVisibilityDescription}); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [visibilityDescription], - ); - /** * @param {Object} values - form input values passed by the Form component * @returns {Boolean} @@ -122,36 +106,44 @@ function WorkspaceNewRoomPage(props) { [props.reports], ); + // Workspaces are policies with type === 'free' + const workspaceOptions = useMemo( + () => + _.map( + _.filter(props.policies, (policy) => policy && policy.type === CONST.POLICY.TYPE.FREE), + (policy) => ({label: policy.name, key: policy.id, value: policy.id}), + ), + [props.policies], + ); + + const visibilityOptions = useMemo( + () => + _.map( + _.filter(_.values(CONST.REPORT.VISIBILITY), (visibilityOption) => visibilityOption !== CONST.REPORT.VISIBILITY.PUBLIC_ANNOUNCE), + (visibilityOption) => ({ + label: translate(`newRoomPage.visibilityOptions.${visibilityOption}`), + value: visibilityOption, + description: translate(`newRoomPage.${visibilityOption}Description`), + }), + ), + [translate], + ); + if (!Permissions.canUsePolicyRooms(props.betas)) { Log.info('Not showing create Policy Room page since user is not on policy rooms beta'); Navigation.dismissModal(); return null; } - // Workspaces are policies with type === 'free' - const workspaceOptions = _.map( - _.filter(props.policies, (policy) => policy && policy.type === CONST.POLICY.TYPE.FREE), - (policy) => ({label: policy.name, key: policy.id, value: policy.id}), - ); - - const visibilityOptions = _.map( - _.filter(_.values(CONST.REPORT.VISIBILITY), (visibilityOption) => visibilityOption !== CONST.REPORT.VISIBILITY.PUBLIC_ANNOUNCE), - (visibilityOption) => ({ - label: props.translate(`newRoomPage.visibilityOptions.${visibilityOption}`), - value: visibilityOption, - description: props.translate(`newRoomPage.${visibilityOption}Description`), - }), - ); - return ( - +
@@ -192,20 +184,17 @@ WorkspaceNewRoomPage.propTypes = propTypes; WorkspaceNewRoomPage.defaultProps = defaultProps; WorkspaceNewRoomPage.displayName = 'WorkspaceNewRoomPage'; -export default compose( - withOnyx({ - betas: { - key: ONYXKEYS.BETAS, - }, - policies: { - key: ONYXKEYS.COLLECTION.POLICY, - }, - reports: { - key: ONYXKEYS.COLLECTION.REPORT, - }, - allPolicyMembers: { - key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, - }, - }), - withLocalize, -)(WorkspaceNewRoomPage); +export default withOnyx({ + betas: { + key: ONYXKEYS.BETAS, + }, + policies: { + key: ONYXKEYS.COLLECTION.POLICY, + }, + reports: { + key: ONYXKEYS.COLLECTION.REPORT, + }, + allPolicyMembers: { + key: ONYXKEYS.COLLECTION.POLICY_MEMBERS, + }, +})(WorkspaceNewRoomPage); From 208cce7029c5979c63293c9664300d981ac7cf63 Mon Sep 17 00:00:00 2001 From: Aleksei Dvoretskii Date: Sun, 2 Jul 2023 17:56:53 -0700 Subject: [PATCH 6/7] Update src/pages/workspace/WorkspaceNewRoomPage.js Co-authored-by: Fedi Rajhi --- src/pages/workspace/WorkspaceNewRoomPage.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index c05430300b76..255ffb5b9e3a 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -129,9 +129,15 @@ function WorkspaceNewRoomPage(props) { [translate], ); - if (!Permissions.canUsePolicyRooms(props.betas)) { + useEffect(() => { + if (Permissions.canUsePolicyRooms(props.betas)) { + return; + } Log.info('Not showing create Policy Room page since user is not on policy rooms beta'); Navigation.dismissModal(); + }, [props.betas]); + + if (!Permissions.canUsePolicyRooms(props.betas)) { return null; } From a1848cbaf395db9a4b8d32c33a2af6a2c2e9edaa Mon Sep 17 00:00:00 2001 From: Alex D Date: Mon, 3 Jul 2023 04:01:13 +0300 Subject: [PATCH 7/7] Fix missing import --- src/pages/workspace/WorkspaceNewRoomPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index 255ffb5b9e3a..c59b6687a809 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.js +++ b/src/pages/workspace/WorkspaceNewRoomPage.js @@ -1,4 +1,4 @@ -import React, {useState, useCallback, useMemo} from 'react'; +import React, {useState, useCallback, useMemo, useEffect} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx';