From b81cd49fb476495be34d0f94aa4c64fa2f3fa542 Mon Sep 17 00:00:00 2001 From: Woolim Cho <2680v4@gmail.com> Date: Wed, 5 Jun 2019 17:11:42 +0900 Subject: [PATCH] [MM-13879] Add Edit profile button to RHS menu and own profile pop-over (#2832) * Add Edit Profile button to right panel menu * Make user info of right panel menu opens the users own profile * Add an Edit button of the users own profile * handle transitions * Add commandType to propTypes * Update test codes * add unit tests for user_profile * Assign commandType manually * Remove async, set delay to 0 --- .../sidebars/settings/settings_sidebar.js | 25 ++++++- .../__snapshots__/edit_profile.test.js.snap | 6 -- app/screens/edit_profile/edit_profile.js | 18 +++-- app/screens/edit_profile/edit_profile.test.js | 1 + app/screens/user_profile/index.js | 2 + app/screens/user_profile/user_profile.js | 67 ++++++++++++++++++ app/screens/user_profile/user_profile.test.js | 69 +++++++++++++++++++ 7 files changed, 170 insertions(+), 18 deletions(-) diff --git a/app/components/sidebars/settings/settings_sidebar.js b/app/components/sidebars/settings/settings_sidebar.js index ffade1249..9d552978b 100644 --- a/app/components/sidebars/settings/settings_sidebar.js +++ b/app/components/sidebars/settings/settings_sidebar.js @@ -153,11 +153,12 @@ export default class SettingsDrawer extends PureComponent { goToEditProfile = preventDoubleTap(() => { const {currentUser} = this.props; const {formatMessage} = this.context.intl; + const commandType = 'ShowModal'; this.openModal( 'EditProfile', formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'}), - {currentUser} + {currentUser, commandType} ); }); @@ -179,6 +180,17 @@ export default class SettingsDrawer extends PureComponent { ); }); + goToUserProfile = preventDoubleTap(() => { + const userId = this.props.currentUser.id; + const {formatMessage} = this.context.intl; + + this.openModal( + 'UserProfile', + formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}), + {userId, fromSettings: true} + ); + }); + goToSettings = preventDoubleTap(() => { const {intl} = this.context; @@ -258,7 +270,7 @@ export default class SettingsDrawer extends PureComponent { contentContainerStyle={style.wrapper} > @@ -293,6 +305,15 @@ export default class SettingsDrawer extends PureComponent { + { - this.props.navigator.dismissModal({ - animationType: 'slide-down', - }); + if (this.props.commandType === 'Push') { + this.props.navigator.pop(); + } else { + this.props.navigator.dismissModal({ + animationType: 'slide-down', + }); + } }; emitCanUpdateAccount = (enabled) => { diff --git a/app/screens/edit_profile/edit_profile.test.js b/app/screens/edit_profile/edit_profile.test.js index 249fedf10..69682f745 100644 --- a/app/screens/edit_profile/edit_profile.test.js +++ b/app/screens/edit_profile/edit_profile.test.js @@ -45,6 +45,7 @@ describe('edit_profile', () => { nickname: 'Dragon', position: 'position', }, + commandType: 'ShowModal', }; test('should match snapshot', async () => { diff --git a/app/screens/user_profile/index.js b/app/screens/user_profile/index.js index a9d6ba836..27b466ed1 100644 --- a/app/screens/user_profile/index.js +++ b/app/screens/user_profile/index.js @@ -12,6 +12,7 @@ import {getConfig} from 'mattermost-redux/selectors/entities/general'; import Preferences from 'mattermost-redux/constants/preferences'; import {loadBot} from 'mattermost-redux/actions/bots'; import {getBotAccounts} from 'mattermost-redux/selectors/entities/bots'; +import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {isTimezoneEnabled} from 'app/utils/timezone'; @@ -33,6 +34,7 @@ function mapStateToProps(state, ownProps) { enableTimezone, militaryTime, theme: getTheme(state), + isMyUser: getCurrentUserId(state) === ownProps.userId, }; } diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js index 9a6ea0e66..f1bf1ba34 100644 --- a/app/screens/user_profile/user_profile.js +++ b/app/screens/user_profile/user_profile.js @@ -42,12 +42,34 @@ export default class UserProfile extends PureComponent { bot: PropTypes.object, militaryTime: PropTypes.bool.isRequired, enableTimezone: PropTypes.bool.isRequired, + isMyUser: PropTypes.bool.isRequired, + fromSettings: PropTypes.bool, }; static contextTypes = { intl: intlShape.isRequired, }; + rightButton = { + id: 'edit-profile', + showAsAction: 'always', + }; + + constructor(props, context) { + super(props); + + if (props.isMyUser) { + this.rightButton.title = context.intl.formatMessage({id: 'mobile.routes.user_profile.edit', defaultMessage: 'Edit'}); + + const buttons = { + rightButtons: [this.rightButton], + }; + + props.navigator.setOnNavigatorEvent(this.onNavigatorEvent); + props.navigator.setButtons(buttons); + } + } + componentWillReceiveProps(nextProps) { if (this.props.theme !== nextProps.theme) { setNavigatorStyles(this.props.navigator, nextProps.theme); @@ -63,6 +85,13 @@ export default class UserProfile extends PureComponent { close = () => { const {navigator, theme} = this.props; + if (this.props.fromSettings) { + navigator.dismissModal({ + animationType: 'slide-down', + }); + return; + } + navigator.resetTo({ screen: 'Channel', animated: true, @@ -187,6 +216,44 @@ export default class UserProfile extends PureComponent { }; }; + goToEditProfile = () => { + const {user: currentUser} = this.props; + const {formatMessage} = this.context.intl; + const commandType = 'Push'; + + const {navigator, theme} = this.props; + const options = { + screen: 'EditProfile', + title: formatMessage({id: 'mobile.routes.edit_profile', defaultMessage: 'Edit Profile'}), + animated: true, + backButtonTitle: '', + passProps: {currentUser, commandType}, + navigatorStyle: { + navBarTextColor: theme.sidebarHeaderTextColor, + navBarBackgroundColor: theme.sidebarHeaderBg, + navBarButtonColor: theme.sidebarHeaderTextColor, + screenBackgroundColor: theme.centerChannelBg, + }, + }; + + requestAnimationFrame(() => { + navigator.push(options); + }); + }; + + onNavigatorEvent = (event) => { + if (event.type === 'NavBarButtonPress') { + switch (event.id) { + case this.rightButton.id: + this.goToEditProfile(); + break; + case 'close-settings': + this.close(); + break; + } + } + }; + renderAdditionalOptions = () => { if (!Config.ExperimentalProfileLinks) { return null; diff --git a/app/screens/user_profile/user_profile.test.js b/app/screens/user_profile/user_profile.test.js index 6b61fe051..e1dac798e 100644 --- a/app/screens/user_profile/user_profile.test.js +++ b/app/screens/user_profile/user_profile.test.js @@ -31,11 +31,14 @@ describe('user_profile', () => { teammateNameDisplay: 'username', navigator: { resetTo: jest.fn(), + push: jest.fn(), + dismissModal: jest.fn(), }, teams: [], theme: Preferences.THEMES.default, enableTimezone: false, militaryTime: false, + isMyUser: false, }; const user = { @@ -84,4 +87,70 @@ describe('user_profile', () => { /> )).toEqual(true); }); + + test('should push EditProfile', async () => { + const props = { + ...baseProps, + navigator: { + push: jest.fn(), + }, + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + + wrapper.instance().goToEditProfile(); + setTimeout(() => { + expect(props.navigator.push).toHaveBeenCalledTimes(1); + }, 16); + }); + + test('should call goToEditProfile', () => { + const props = { + ...baseProps, + navigator: { + push: jest.fn(), + }, + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + + const event = {type: 'NavBarButtonPress', id: wrapper.instance().rightButton.id}; + wrapper.instance().onNavigatorEvent(event); + setTimeout(() => { + expect(props.navigator.push).toHaveBeenCalledTimes(1); + }, 0); + }); + + test('should close', async () => { + const props = {...baseProps, fromSettings: true}; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + + const event = {type: 'NavBarButtonPress', id: 'close-settings'}; + wrapper.instance().onNavigatorEvent(event); + expect(props.navigator.dismissModal).toHaveBeenCalledTimes(1); + + props.fromSettings = false; + wrapper.setProps({...props}); + wrapper.instance().onNavigatorEvent(event); + expect(props.navigator.resetTo).toHaveBeenCalledTimes(1); + }); });