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

Component refactor: migrate WorkspaceNewRoomPage to function component #22015

Merged
merged 7 commits into from
Jul 3, 2023
Merged
Changes from all commits
Commits
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
259 changes: 125 additions & 134 deletions src/pages/workspace/WorkspaceNewRoomPage.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react';
import React, {useState, useCallback, useMemo, useEffect} 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';
Expand Down Expand Up @@ -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: [],
Expand All @@ -65,151 +62,145 @@ const defaultProps = {
allPolicyMembers: {},
};

alexxxwork marked this conversation as resolved.
Show resolved Hide resolved
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 {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
*/
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) {
return;
}
this.setState({visibilityDescription});
}
};

/**
* @param {Object} values - form input values passed by the Form component
* @returns {Boolean}
*/
validate(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, this.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';
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],
);

// 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],
);

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]);

return errors;
if (!Permissions.canUsePolicyRooms(props.betas)) {
return null;
}

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;
}

// 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 (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnablePickerAvoiding={false}
return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
shouldEnablePickerAvoiding={false}
>
<HeaderWithBackButton title={translate('newRoomPage.newRoom')} />
<Form
formID={ONYXKEYS.FORMS.NEW_ROOM_FORM}
submitButtonText={translate('newRoomPage.createRoom')}
scrollContextEnabled
style={[styles.mh5, styles.flexGrow1]}
validate={validate}
onSubmit={submit}
enabledWhenOffline
>
<HeaderWithBackButton title={this.props.translate('newRoomPage.newRoom')} />
<Form
formID={ONYXKEYS.FORMS.NEW_ROOM_FORM}
submitButtonText={this.props.translate('newRoomPage.createRoom')}
scrollContextEnabled
style={[styles.mh5, styles.mt5, styles.flexGrow1]}
validate={this.validate}
onSubmit={this.submit}
enabledWhenOffline
>
<View style={styles.mb5}>
<RoomNameInput
inputID="roomName"
autoFocus
shouldDelayFocus={shouldDelayFocus}
/>
</View>
<View style={styles.mb5}>
<Picker
inputID="policyID"
label={this.props.translate('workspace.common.workspace')}
placeholder={{value: '', label: this.props.translate('newRoomPage.selectAWorkspace')}}
items={workspaceOptions}
/>
</View>
<View style={styles.mb2}>
<Picker
inputID="visibility"
label={this.props.translate('newRoomPage.visibility')}
items={visibilityOptions}
onValueChange={this.updateVisibilityDescription}
defaultValue={CONST.REPORT.VISIBILITY.RESTRICTED}
/>
</View>
<Text style={[styles.textLabel, styles.colorMuted]}>{this.state.visibilityDescription}</Text>
</Form>
</ScreenWrapper>
);
}
<View style={styles.mb5}>
<RoomNameInput
inputID="roomName"
autoFocus
shouldDelayFocus={shouldDelayFocus}
/>
</View>
<View style={styles.mb5}>
<Picker
inputID="policyID"
label={translate('workspace.common.workspace')}
placeholder={{value: '', label: translate('newRoomPage.selectAWorkspace')}}
items={workspaceOptions}
/>
</View>
<View style={styles.mb2}>
<Picker
inputID="visibility"
label={translate('newRoomPage.visibility')}
items={visibilityOptions}
onValueChange={setVisibility}
defaultValue={CONST.REPORT.VISIBILITY.RESTRICTED}
/>
</View>
<Text style={[styles.textLabel, styles.colorMuted]}>{visibilityDescription}</Text>
</Form>
</ScreenWrapper>
);
}

WorkspaceNewRoomPage.propTypes = propTypes;
WorkspaceNewRoomPage.defaultProps = defaultProps;

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);
WorkspaceNewRoomPage.displayName = '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);