From 5b16a9059a91b9183ee474022f49650eb2711f49 Mon Sep 17 00:00:00 2001 From: Devin Binnie Date: Wed, 26 Aug 2020 09:08:13 -0400 Subject: [PATCH 1/3] [MM-28099] Menu Item to return to Getting Started --- actions/views/next_steps.ts | 21 ++++++++++++++++++- components/main_menu/index.jsx | 8 ++++++- components/main_menu/main_menu.jsx | 8 +++++++ components/next_steps_view/steps.ts | 12 +++++++++-- .../sidebar_next_steps/sidebar_next_steps.tsx | 4 ++-- 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/actions/views/next_steps.ts b/actions/views/next_steps.ts index 1115df66e16a..cfa6afa7d12e 100644 --- a/actions/views/next_steps.ts +++ b/actions/views/next_steps.ts @@ -1,7 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {ActionTypes} from 'utils/constants'; +import {savePreferences} from 'mattermost-redux/actions/preferences'; +import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; +import {DispatchFunc, GetStateFunc} from 'mattermost-redux/types/actions'; + +import {ActionTypes, Preferences, RecommendedNextSteps} from 'utils/constants'; export function setShowNextStepsView(show: boolean) { return { @@ -9,3 +13,18 @@ export function setShowNextStepsView(show: boolean) { show, }; } + +export const unhideNextSteps = () => { + return async (dispatch: DispatchFunc, getState: GetStateFunc) => { + const userId = getCurrentUserId(getState()); + + dispatch(setShowNextStepsView(true)); + + dispatch(savePreferences(userId, [{ + user_id: userId, + category: Preferences.RECOMMENDED_NEXT_STEPS, + name: RecommendedNextSteps.HIDE, + value: 'false', + }])); + }; +}; diff --git a/components/main_menu/index.jsx b/components/main_menu/index.jsx index 4ae30a57484d..a533322666a2 100644 --- a/components/main_menu/index.jsx +++ b/components/main_menu/index.jsx @@ -4,7 +4,7 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {getConfig} from 'mattermost-redux/selectors/entities/general'; +import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; import {getMyTeams, getJoinableTeamIds, getCurrentTeam} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {haveITeamPermission, haveICurrentTeamPermission, haveISystemPermission} from 'mattermost-redux/selectors/entities/roles'; @@ -12,16 +12,20 @@ import {Permissions} from 'mattermost-redux/constants'; import {RHSStates} from 'utils/constants'; +import {unhideNextSteps} from 'actions/views/next_steps'; import {showMentions, showFlaggedPosts, closeRightHandSide, closeMenu as closeRhsMenu} from 'actions/views/rhs'; import {openModal} from 'actions/views/modals'; import {getRhsState} from 'selectors/rhs'; +import {nextStepsNotFinished} from 'components/next_steps_view/steps'; + import MainMenu from './main_menu.jsx'; function mapStateToProps(state) { const config = getConfig(state); const currentTeam = getCurrentTeam(state); const currentUser = getCurrentUser(state); + const license = getLicense(state); const appDownloadLink = config.AppDownloadLink; const enableCommands = config.EnableCommands === 'true'; @@ -82,6 +86,7 @@ function mapStateToProps(state) { isMentionSearch: rhsState === RHSStates.MENTION, teamIsGroupConstrained: Boolean(currentTeam.group_constrained), isLicensedForLDAPGroups: state.entities.general.license.LDAPGroups === 'true', + showGettingStarted: !state.views.nextSteps.show && nextStepsNotFinished(state) && license.Cloud === 'true', }; } @@ -93,6 +98,7 @@ function mapDispatchToProps(dispatch) { showFlaggedPosts, closeRightHandSide, closeRhsMenu, + unhideNextSteps, }, dispatch), }; } diff --git a/components/main_menu/main_menu.jsx b/components/main_menu/main_menu.jsx index 4605cc13b4e8..967e60809138 100644 --- a/components/main_menu/main_menu.jsx +++ b/components/main_menu/main_menu.jsx @@ -59,6 +59,7 @@ class MainMenu extends React.PureComponent { isMentionSearch: PropTypes.bool, teamIsGroupConstrained: PropTypes.bool.isRequired, isLicensedForLDAPGroups: PropTypes.bool, + showGettingStarted: PropTypes.bool.isRequired, intl: intlShape.isRequired, actions: PropTypes.shape({ openModal: PropTypes.func.isRequred, @@ -66,6 +67,7 @@ class MainMenu extends React.PureComponent { showFlaggedPosts: PropTypes.func, closeRightHandSide: PropTypes.func.isRequired, closeRhsMenu: PropTypes.func.isRequired, + unhideNextSteps: PropTypes.func.isRequired, }).isRequired, }; @@ -330,6 +332,12 @@ class MainMenu extends React.PureComponent { text={formatMessage({id: 'navbar_dropdown.help', defaultMessage: 'Help'})} icon={this.props.mobile && } /> + this.props.actions.unhideNextSteps()} + text={formatMessage({id: 'navbar_dropdown.gettingStarted', defaultMessage: 'Getting Started'})} + /> getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), (state: GlobalState) => getLicense(state), - (stepPreferences, license) => { - if (stepPreferences.some((pref) => pref.name === RecommendedNextSteps.HIDE && pref.value)) { + (state: GlobalState) => nextStepsNotFinished(state), + (stepPreferences, license, nextStepsNotFinished) => { + if (stepPreferences.some((pref) => pref.name === RecommendedNextSteps.HIDE && pref.value === 'true')) { return false; } @@ -58,6 +59,13 @@ export const showNextSteps = createSelector( return false; } + return nextStepsNotFinished; + } +); + +export const nextStepsNotFinished = createSelector( + (state: GlobalState) => getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS), + (stepPreferences) => { const checkPref = (step: StepType) => stepPreferences.some((pref) => pref.name === step.id && pref.value); return !Steps.every(checkPref); } diff --git a/components/sidebar/sidebar_next_steps/sidebar_next_steps.tsx b/components/sidebar/sidebar_next_steps/sidebar_next_steps.tsx index f7b8bb11f06f..5b302bd5fb17 100644 --- a/components/sidebar/sidebar_next_steps/sidebar_next_steps.tsx +++ b/components/sidebar/sidebar_next_steps/sidebar_next_steps.tsx @@ -77,7 +77,7 @@ export default class SidebarNextSteps extends React.PureComponent } render() { - if (this.props.preferences.some((pref) => pref.name === RecommendedNextSteps.HIDE && pref.value)) { + if (this.props.preferences.some((pref) => pref.name === RecommendedNextSteps.HIDE && pref.value === 'true')) { return null; } @@ -86,7 +86,7 @@ export default class SidebarNextSteps extends React.PureComponent } const total = Steps.length; - const complete = this.props.preferences.filter((pref) => pref.value).length; + const complete = this.props.preferences.filter((pref) => pref.name !== RecommendedNextSteps.HIDE && pref.value === 'true').length; let header = ( Date: Wed, 26 Aug 2020 11:01:03 -0400 Subject: [PATCH 2/3] Translation fix --- i18n/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/en.json b/i18n/en.json index 020a10667c1f..ca5a664511d6 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -3069,6 +3069,7 @@ "navbar_dropdown.console": "System Console", "navbar_dropdown.create": "Create a Team", "navbar_dropdown.emoji": "Custom Emoji", + "navbar_dropdown.gettingStarted": "Getting Started", "navbar_dropdown.help": "Help", "navbar_dropdown.integrations": "Integrations", "navbar_dropdown.invitePeople": "Invite People", From 2ce89a22169e4f1b1a9ad2c3aeba4fd8cb4b42d4 Mon Sep 17 00:00:00 2001 From: Devin Binnie Date: Wed, 26 Aug 2020 11:53:23 -0400 Subject: [PATCH 3/3] Test fixes --- .../__snapshots__/main_menu.test.jsx.snap | 42 +++++++++++++++++++ components/main_menu/main_menu.test.jsx | 2 + components/next_steps_view/steps.test.tsx | 8 ++-- .../main_menu_action.test.jsx.snap | 6 +++ plugins/test/main_menu_action.test.jsx | 2 + 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/components/main_menu/__snapshots__/main_menu.test.jsx.snap b/components/main_menu/__snapshots__/main_menu.test.jsx.snap index f91c2d7b5312..b73c6a01b9ee 100644 --- a/components/main_menu/__snapshots__/main_menu.test.jsx.snap +++ b/components/main_menu/__snapshots__/main_menu.test.jsx.snap @@ -308,6 +308,12 @@ exports[`components/Menu should match snapshot with id 1`] = ` text="Help" url={null} /> + + + + + + + { moreTeamsToJoin: false, pluginMenuItems: [], isMentionSearch: false, + showGettingStarted: false, actions: { openModal: jest.fn(), showMentions: jest.fn(), showFlaggedPosts: jest.fn(), closeRightHandSide: jest.fn(), closeRhsMenu: jest.fn(), + unhideNextSteps: jest.fn(), }, teamIsGroupConstrained: false, }; diff --git a/components/next_steps_view/steps.test.tsx b/components/next_steps_view/steps.test.tsx index 5ccf238c05f0..6fa6411e984b 100644 --- a/components/next_steps_view/steps.test.tsx +++ b/components/next_steps_view/steps.test.tsx @@ -46,7 +46,7 @@ describe('components/next_steps_view/steps', () => { }, preferences: { myPreferences: { - 'recommended_next_steps--hide': {name: 'hide', value: true}, + 'recommended_next_steps--hide': {name: 'hide', value: 'true'}, }, }, }, @@ -65,9 +65,9 @@ describe('components/next_steps_view/steps', () => { }, preferences: { myPreferences: { - 'recommended_next_steps--complete_profile': {name: 'complete_profile', value: true}, - 'recommended_next_steps--team_setup': {name: 'team_setup', value: true}, - 'recommended_next_steps--invite_members': {name: 'invite_members', value: true}, + 'recommended_next_steps--complete_profile': {name: 'complete_profile', value: 'true'}, + 'recommended_next_steps--team_setup': {name: 'team_setup', value: 'true'}, + 'recommended_next_steps--invite_members': {name: 'invite_members', value: 'true'}, }, }, }, diff --git a/plugins/test/__snapshots__/main_menu_action.test.jsx.snap b/plugins/test/__snapshots__/main_menu_action.test.jsx.snap index 83b008e283b5..88806eb4cd3d 100644 --- a/plugins/test/__snapshots__/main_menu_action.test.jsx.snap +++ b/plugins/test/__snapshots__/main_menu_action.test.jsx.snap @@ -315,6 +315,12 @@ exports[`plugins/MainMenuActions should match snapshot and click plugin item for show={false} text="Help" /> + { canManageIntegrations: true, moreTeamsToJoin: true, teamIsGroupConstrained: true, + showGettingStarted: true, actions: { openModal: jest.fn(), showMentions: jest.fn(), showFlaggedPosts: jest.fn(), closeRightHandSide: jest.fn(), closeRhsMenu: jest.fn(), + unhideNextSteps: jest.fn(), }, };