diff --git a/src/CONST.js b/src/CONST.js index d13b17bb541a..3f98db8c5942 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1196,6 +1196,7 @@ const CONST = { MEMBERS: 'member', SETTINGS: 'settings', LEAVE_ROOM: 'leaveRoom', + WELCOME_MESSAGE: 'welcomeMessage', }, FOOTER: { diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 1805db98f1d5..9e282e478e89 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -198,6 +198,7 @@ export default { PROFILE_SETTINGS_FORM: 'profileSettingsForm', DISPLAY_NAME_FORM: 'displayNameForm', ROOM_NAME_FORM: 'roomNameForm', + WELCOME_MESSAGE_FORM: 'welcomeMessageForm', LEGAL_NAME_FORM: 'legalNameForm', WORKSPACE_INVITE_MESSAGE_FORM: 'workspaceInviteMessageForm', DATE_OF_BIRTH_FORM: 'dateOfBirthForm', diff --git a/src/ROUTES.js b/src/ROUTES.js index b6eea9b7a320..3275d4c06f31 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -117,12 +117,14 @@ export default { REPORT_WITH_ID_DETAILS: 'r/:reportID/details', getReportDetailsRoute: (reportID) => `r/${reportID}/details`, REPORT_SETTINGS: 'r/:reportID/settings', - REPORT_SETTINGS_ROOM_NAME: 'r/:reportID/settings/room-name', - REPORT_SETTINGS_NOTIFICATION_PREFERENCES: 'r/:reportID/settings/notification-preferences', - REPORT_SETTINGS_WRITE_CAPABILITY: 'r/:reportID/settings/who-can-post', getReportSettingsRoute: (reportID) => `r/${reportID}/settings`, + REPORT_SETTINGS_ROOM_NAME: 'r/:reportID/settings/room-name', getReportSettingsRoomNameRoute: (reportID) => `r/${reportID}/settings/room-name`, + REPORT_SETTINGS_NOTIFICATION_PREFERENCES: 'r/:reportID/settings/notification-preferences', getReportSettingsNotificationPreferencesRoute: (reportID) => `r/${reportID}/settings/notification-preferences`, + REPORT_WELCOME_MESSAGE: 'r/:reportID/welcomeMessage', + getReportWelcomeMessageRoute: (reportID) => `r/${reportID}/welcomeMessage`, + REPORT_SETTINGS_WRITE_CAPABILITY: 'r/:reportID/settings/who-can-post', getReportSettingsWriteCapabilityRoute: (reportID) => `r/${reportID}/settings/who-can-post`, TRANSITION_FROM_OLD_DOT: 'transition', VALIDATE_LOGIN: 'v/:accountID/:validateCode', diff --git a/src/languages/en.js b/src/languages/en.js index 1e6d17c7cc85..9185c2434fd8 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -639,6 +639,10 @@ export default { }, }, }, + welcomeMessagePage: { + welcomeMessage: 'Welcome message', + explainerText: 'Set a custom welcome message that will be sent to users when they join this room.', + }, languagePage: { language: 'Language', languages: { diff --git a/src/languages/es.js b/src/languages/es.js index 6035919e0dfb..a95f3dc80431 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -640,6 +640,10 @@ export default { }, }, }, + welcomeMessagePage: { + welcomeMessage: 'Mensaje de bienvenida', + explainerText: 'Configura un mensaje de bienvenida privado y personalizado que se enviará cuando los usuarios se unan a esta sala de chat.', + }, languagePage: { language: 'Idioma', languages: { diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 7f48a2ffb625..6a00bc750e9a 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -298,6 +298,12 @@ class AuthScreens extends React.Component { component={ModalStackNavigators.ReportSettingsModalStackNavigator} listeners={modalScreenListeners} /> + { + const ReportWelcomeMessagePage = require('../../../pages/ReportWelcomeMessagePage').default; + return ReportWelcomeMessagePage; + }, + name: 'Report_WelcomeMessage_Root', + }, +]); + const ReportParticipantsModalStackNavigator = createModalStackNavigator([ { getComponent: () => { @@ -683,6 +693,7 @@ export { ReportDetailsModalStackNavigator, TaskModalStackNavigator, ReportSettingsModalStackNavigator, + ReportWelcomeMessageModalStackNavigator, ReportParticipantsModalStackNavigator, SearchModalStackNavigator, NewGroupModalStackNavigator, diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index b0471671b96c..6c6c0776fb17 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -229,6 +229,11 @@ export default { }, }, }, + Report_WelcomeMessage: { + screens: { + Report_WelcomeMessage_Root: ROUTES.REPORT_WELCOME_MESSAGE, + }, + }, NewGroup: { screens: { NewGroup_Root: ROUTES.NEW_GROUP, diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 392f55015622..1171a073f1db 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -1092,6 +1092,37 @@ function updateNotificationPreferenceAndNavigate(reportID, previousValue, newVal Navigation.drawerGoBack(ROUTES.getReportSettingsRoute(reportID)); } +/** + * @param {String} reportID + * @param {String} previousValue + * @param {String} newValue + */ +function updateWelcomeMessage(reportID, previousValue, newValue) { + // No change needed, navigate back + if (previousValue === newValue) { + Navigation.goBack(); + return; + } + + const parsedWelcomeMessage = ReportUtils.getParsedComment(newValue); + const optimisticData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {welcomeMessage: newValue}, + }, + ]; + const failureData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {welcomeMessage: previousValue}, + }, + ]; + API.write('UpdateWelcomeMessage', {reportID, welcomeMessage: parsedWelcomeMessage}, {optimisticData, failureData}); + Navigation.goBack(); +} + /** * @param {Object} report * @param {String} newValue @@ -1642,6 +1673,7 @@ export { addComment, addAttachment, reconnect, + updateWelcomeMessage, updateWriteCapabilityAndNavigate, updateNotificationPreferenceAndNavigate, subscribeToReportTypingEvents, diff --git a/src/pages/ReportWelcomeMessagePage.js b/src/pages/ReportWelcomeMessagePage.js new file mode 100644 index 000000000000..60ffbebb3638 --- /dev/null +++ b/src/pages/ReportWelcomeMessagePage.js @@ -0,0 +1,94 @@ +import React, {useCallback, useRef, useState} from 'react'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {View} from 'react-native'; +import ExpensiMark from 'expensify-common/lib/ExpensiMark'; +import compose from '../libs/compose'; +import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; +import ScreenWrapper from '../components/ScreenWrapper'; +import Navigation from '../libs/Navigation/Navigation'; +import HeaderWithCloseButton from '../components/HeaderWithCloseButton'; +import styles from '../styles/styles'; +import reportPropTypes from './reportPropTypes'; +import withReportOrNotFound from './home/report/withReportOrNotFound'; +import Text from '../components/Text'; +import TextInput from '../components/TextInput'; +import * as Report from '../libs/actions/Report'; +import ONYXKEYS from '../ONYXKEYS'; +import CONST from '../CONST'; +import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; +import Form from '../components/Form'; + +const propTypes = { + ...withLocalizePropTypes, + + /** The report currently being looked at */ + report: reportPropTypes.isRequired, + + /** Route params */ + route: PropTypes.shape({ + params: PropTypes.shape({ + /** Report ID passed via route r/:reportID/welcomeMessage */ + reportID: PropTypes.string, + }), + }).isRequired, +}; + +function ReportWelcomeMessagePage(props) { + const parser = new ExpensiMark(); + const [welcomeMessage, setWelcomeMessage] = useState(parser.htmlToMarkdown(props.report.welcomeMessage)); + const welcomeMessageInputRef = useRef(null); + + const handleWelcomeMessageChange = useCallback((value) => { + setWelcomeMessage(value); + }, []); + + const submitForm = useCallback(() => { + Report.updateWelcomeMessage(props.report.reportID, props.report.welcomeMessage, welcomeMessage); + }, [props.report.reportID, props.report.welcomeMessage, welcomeMessage]); + + return ( + { + if (!welcomeMessageInputRef.current) { + return; + } + welcomeMessageInputRef.current.focus(); + }} + > + + Navigation.goBack()} + onCloseButtonPress={() => Navigation.dismissModal()} + /> +
({})} + submitButtonText={props.translate('common.save')} + enabledWhenOffline + > + {props.translate('welcomeMessagePage.explainerText')} + + + +
+
+
+ ); +} + +ReportWelcomeMessagePage.propTypes = propTypes; +export default compose(withLocalize, withReportOrNotFound)(ReportWelcomeMessagePage); diff --git a/src/pages/settings/Report/ReportSettingsPage.js b/src/pages/settings/Report/ReportSettingsPage.js index 6e3b460411de..aaf4da94b959 100644 --- a/src/pages/settings/Report/ReportSettingsPage.js +++ b/src/pages/settings/Report/ReportSettingsPage.js @@ -22,6 +22,8 @@ import withReportOrNotFound from '../../home/report/withReportOrNotFound'; import FullPageNotFoundView from '../../../components/BlockingViews/FullPageNotFoundView'; import MenuItemWithTopDescription from '../../../components/MenuItemWithTopDescription'; import ROUTES from '../../../ROUTES'; +import * as Expensicons from '../../../components/Icon/Expensicons'; +import MenuItem from '../../../components/MenuItem'; const propTypes = { /** Route params */ @@ -79,11 +81,22 @@ class ReportSettingsPage extends Component { return !Policy.isPolicyOwner(linkedWorkspace) && linkedWorkspace.role !== CONST.POLICY.ROLE.ADMIN; } + /** + * We only want policy owners and admins to be able to modify the welcome message. + * + * @param {Object|null} linkedWorkspace - the workspace the report is on, null if the user isn't a member of the workspace + * @returns {Boolean} + */ + shouldDisableWelcomeMessage(linkedWorkspace) { + return !ReportUtils.isArchivedRoom(this.props.report) && !_.isEmpty(linkedWorkspace) && Policy.isPolicyOwner(linkedWorkspace) && linkedWorkspace.role === CONST.POLICY.ROLE.ADMIN; + } + render() { const shouldShowRoomName = !ReportUtils.isPolicyExpenseChat(this.props.report) && !ReportUtils.isThread(this.props.report); const linkedWorkspace = _.find(this.props.policies, (policy) => policy && policy.id === this.props.report.policyID); const shouldDisableRename = this.shouldDisableRename(linkedWorkspace) || ReportUtils.isThread(this.props.report); const notificationPreference = this.props.translate(`notificationPreferencesPage.notificationPreferences.${this.props.report.notificationPreference}`); + const shouldDisableWelcomeMessage = this.shouldDisableRename(linkedWorkspace); const writeCapability = this.props.report.writeCapability || CONST.REPORT.WRITE_CAPABILITIES.ALL; const writeCapabilityText = this.props.translate(`writeCapabilityPage.writeCapability.${writeCapability}`); const shouldAllowWriteCapabilityEditing = lodashGet(linkedWorkspace, 'role', '') === CONST.POLICY.ROLE.ADMIN; @@ -196,6 +209,14 @@ class ReportSettingsPage extends Component { )} + {!shouldDisableWelcomeMessage && ( + Navigation.navigate(ROUTES.getReportWelcomeMessageRoute(this.props.report.reportID))} + shouldShowRightIcon + /> + )} );