diff --git a/src/components/ValuePicker/ValueSelectorModal.js b/src/components/ValuePicker/ValueSelectorModal.js new file mode 100644 index 000000000000..23aac4839d2a --- /dev/null +++ b/src/components/ValuePicker/ValueSelectorModal.js @@ -0,0 +1,84 @@ +import React, {useState, useEffect} from 'react'; +import PropTypes from 'prop-types'; +import _ from 'lodash'; +import CONST from '../../CONST'; +import HeaderWithBackButton from '../HeaderWithBackButton'; +import SelectionList from '../SelectionList'; +import Modal from '../Modal'; +import ScreenWrapper from '../ScreenWrapper'; +import styles from '../../styles/styles'; + +const propTypes = { + /** Whether the modal is visible */ + isVisible: PropTypes.bool.isRequired, + + /** Current value selected */ + currentValue: PropTypes.string, + + /** Items to pick from */ + items: PropTypes.arrayOf(PropTypes.shape({value: PropTypes.string, label: PropTypes.string})), + + /** The selected item */ + selectedItem: PropTypes.shape({value: PropTypes.string, label: PropTypes.string}), + + /** Label for values */ + label: PropTypes.string, + + /** Function to call when the user selects a item */ + onItemSelected: PropTypes.func, + + /** Function to call when the user closes the modal */ + onClose: PropTypes.func, +}; + +const defaultProps = { + currentValue: '', + items: [], + selectedItem: {}, + label: '', + onClose: () => {}, + onItemSelected: () => {}, +}; + +function ValueSelectorModal({currentValue, items, selectedItem, label, isVisible, onClose, onItemSelected}) { + const [sectionsData, setSectionsData] = useState([]); + + useEffect(() => { + const itemsData = _.map(items, (item) => ({value: item.value, keyForList: item.value, text: item.label, isSelected: item === selectedItem})); + setSectionsData(itemsData); + }, [items, selectedItem]); + + return ( + + + + + + + ); +} + +ValueSelectorModal.propTypes = propTypes; +ValueSelectorModal.defaultProps = defaultProps; +ValueSelectorModal.displayName = 'ValueSelectorModal'; + +export default ValueSelectorModal; diff --git a/src/components/ValuePicker/index.js b/src/components/ValuePicker/index.js new file mode 100644 index 000000000000..161fbbfadb8b --- /dev/null +++ b/src/components/ValuePicker/index.js @@ -0,0 +1,102 @@ +import React, {useState} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import _ from 'lodash'; +import styles from '../../styles/styles'; +import MenuItemWithTopDescription from '../MenuItemWithTopDescription'; +import ValueSelectorModal from './ValueSelectorModal'; +import FormHelpMessage from '../FormHelpMessage'; +import refPropTypes from '../refPropTypes'; + +const propTypes = { + /** Form Error description */ + errorText: PropTypes.string, + + /** Item to display */ + value: PropTypes.string, + + /** A placeholder value to display */ + placeholder: PropTypes.string, + + /** Items to pick from */ + items: PropTypes.arrayOf(PropTypes.shape({value: PropTypes.string, label: PropTypes.string})), + + /** Label of picker */ + label: PropTypes.string, + + /** Callback to call when the input changes */ + onInputChange: PropTypes.func, + + /** A ref to forward to MenuItemWithTopDescription */ + forwardedRef: refPropTypes, +}; + +const defaultProps = { + value: undefined, + label: undefined, + placeholder: '', + items: {}, + forwardedRef: undefined, + errorText: '', + onInputChange: () => {}, +}; + +function ValuePicker({value, label, items, placeholder, errorText, onInputChange, forwardedRef}) { + const [isPickerVisible, setIsPickerVisible] = useState(false); + + const showPickerModal = () => { + setIsPickerVisible(true); + }; + + const hidePickerModal = () => { + setIsPickerVisible(false); + }; + + const updateInput = (item) => { + if (item.value !== value) { + onInputChange(item.value); + } + hidePickerModal(); + }; + + const descStyle = value.length === 0 ? styles.textNormal : null; + const selectedItem = _.find(items, {value}); + const selectedLabel = selectedItem ? selectedItem.label : ''; + + return ( + + + + + + + + ); +} + +ValuePicker.propTypes = propTypes; +ValuePicker.defaultProps = defaultProps; +ValuePicker.displayName = 'ValuePicker'; + +export default React.forwardRef((props, ref) => ( + +)); diff --git a/src/languages/en.ts b/src/languages/en.ts index 142a4ca4d3ba..fef4979357fa 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -869,6 +869,7 @@ export default { }, welcomeMessagePage: { welcomeMessage: 'Welcome message', + welcomeMessageOptional: 'Welcome message (optional)', explainerText: 'Set a custom welcome message that will be sent to users when they join this room.', }, languagePage: { diff --git a/src/languages/es.ts b/src/languages/es.ts index fa97556d8096..abfcf1218566 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -866,6 +866,7 @@ export default { }, welcomeMessagePage: { welcomeMessage: 'Mensaje de bienvenida', + welcomeMessageOptional: 'Mensaje de bienvenida (opcional)', explainerText: 'Configura un mensaje de bienvenida privado y personalizado que se enviará cuando los usuarios se unan a esta sala de chat.', }, languagePage: { diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 806b9dcae417..647af48c6039 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2547,6 +2547,7 @@ function buildOptimisticTaskReportAction(taskReportID, actionName, message = '') * @param {String} notificationPreference * @param {String} parentReportActionID * @param {String} parentReportID + * @param {String} welcomeMessage * @returns {Object} */ function buildOptimisticChatReport( @@ -2562,6 +2563,7 @@ function buildOptimisticChatReport( notificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, parentReportActionID = '', parentReportID = '', + welcomeMessage = '', ) { const currentTime = DateUtils.getDBTime(); return { @@ -2588,7 +2590,7 @@ function buildOptimisticChatReport( stateNum: 0, statusNum: 0, visibility, - welcomeMessage: '', + welcomeMessage, writeCapability, }; } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index e21d9fdd75c6..6f113f201b39 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -1410,8 +1410,9 @@ function navigateToConciergeChat() { * @param {String} visibility * @param {Array} policyMembersAccountIDs * @param {String} writeCapability + * @param {String} welcomeMessage */ -function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs, writeCapability = CONST.REPORT.WRITE_CAPABILITIES.ALL) { +function addPolicyReport(policyID, reportName, visibility, policyMembersAccountIDs, writeCapability = CONST.REPORT.WRITE_CAPABILITIES.ALL, welcomeMessage = '') { // The participants include the current user (admin), and for restricted rooms, the policy members. Participants must not be empty. const members = visibility === CONST.REPORT.VISIBILITY.RESTRICTED ? policyMembersAccountIDs : []; const participants = _.unique([currentUserAccountID, ...members]); @@ -1428,6 +1429,9 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI // The room might contain all policy members so notifying always should be opt-in only. CONST.REPORT.NOTIFICATION_PREFERENCE.DAILY, + '', + '', + welcomeMessage, ); const createdReportAction = ReportUtils.buildOptimisticCreatedReportAction(CONST.POLICY.OWNER_EMAIL_FAKE); @@ -1492,6 +1496,7 @@ function addPolicyReport(policyID, reportName, visibility, policyMembersAccountI reportID: policyReport.reportID, createdReportActionID: createdReportAction.reportActionID, writeCapability, + welcomeMessage, }, {optimisticData, successData, failureData}, ); diff --git a/src/pages/workspace/WorkspaceNewRoomPage.js b/src/pages/workspace/WorkspaceNewRoomPage.js index d6f58a1b66ad..e142c3be2cb8 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, useEffect, useCallback, useMemo} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -9,12 +9,12 @@ import * as App from '../../libs/actions/App'; import useLocalize from '../../hooks/useLocalize'; import styles from '../../styles/styles'; import RoomNameInput from '../../components/RoomNameInput'; -import Picker from '../../components/Picker'; import KeyboardAvoidingView from '../../components/KeyboardAvoidingView'; import ScreenWrapper from '../../components/ScreenWrapper'; import ONYXKEYS from '../../ONYXKEYS'; import CONST from '../../CONST'; import Text from '../../components/Text'; +import TextInput from '../../components/TextInput'; import Permissions from '../../libs/Permissions'; import * as ErrorUtils from '../../libs/ErrorUtils'; import * as ValidationUtils from '../../libs/ValidationUtils'; @@ -25,6 +25,7 @@ import policyMemberPropType from '../policyMemberPropType'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; import compose from '../../libs/compose'; import variables from '../../styles/variables'; +import ValuePicker from '../../components/ValuePicker'; const propTypes = { /** All reports shared with the user */ @@ -72,6 +73,7 @@ function WorkspaceNewRoomPage(props) { const {translate} = useLocalize(); const [visibility, setVisibility] = useState(CONST.REPORT.VISIBILITY.RESTRICTED); const [policyID, setPolicyID] = useState(null); + const [writeCapability, setWriteCapability] = useState(CONST.REPORT.WRITE_CAPABILITIES.ALL); const visibilityDescription = useMemo(() => translate(`newRoomPage.${visibility}Description`), [translate, visibility]); const isPolicyAdmin = useMemo(() => { if (!policyID) { @@ -86,9 +88,17 @@ function WorkspaceNewRoomPage(props) { */ 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, values.writeCapability); + Report.addPolicyReport(policyID, values.roomName, visibility, policyMembers, writeCapability, values.welcomeMessage); }; + useEffect(() => { + if (isPolicyAdmin) { + return; + } + + setWriteCapability(CONST.REPORT.WRITE_CAPABILITIES.ALL); + }, [policyID, isPolicyAdmin]); + /** * @param {Object} values - form input values passed by the Form component * @returns {Boolean} @@ -169,7 +179,6 @@ function WorkspaceNewRoomPage(props) {
- - + + + + {isPolicyAdmin && ( - - + )} - - + {visibilityDescription}