diff --git a/webapp/channels/src/actions/global_actions.tsx b/webapp/channels/src/actions/global_actions.tsx index 6ac09280ab..b658499c4c 100644 --- a/webapp/channels/src/actions/global_actions.tsx +++ b/webapp/channels/src/actions/global_actions.tsx @@ -12,8 +12,8 @@ import { import {logout, loadMe, loadMeREST} from 'mattermost-redux/actions/users'; import {Preferences} from 'mattermost-redux/constants'; import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selectors/entities/general'; -import {getCurrentTeamId, getMyTeams, getTeam, getMyTeamMember, getTeamMemberships} from 'mattermost-redux/selectors/entities/teams'; -import {getBool, isCollapsedThreadsEnabled, isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; +import {getCurrentTeamId, getMyTeams, getTeam, getMyTeamMember, getTeamMemberships, getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams'; +import {getBool, getIsOnboardingFlowEnabled, isCollapsedThreadsEnabled, isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUser, getCurrentUserId, isFirstAdmin} from 'mattermost-redux/selectors/entities/users'; import {getCurrentChannelStats, getCurrentChannelId, getMyChannelMember, getRedirectChannelNameForTeam, getChannelsNameMapInTeam, getAllDirectChannels, getChannelMessageCount} from 'mattermost-redux/selectors/entities/channels'; import {appsEnabled} from 'mattermost-redux/selectors/entities/apps'; @@ -352,7 +352,7 @@ export async function redirectUserToDefaultTeam() { // Assume we need to load the user if they don't have any team memberships loaded or the user loaded let user = getCurrentUser(state); const shouldLoadUser = Utils.isEmptyObject(getTeamMemberships(state)) || !user; - + const onboardingFlowEnabled = getIsOnboardingFlowEnabled(state); if (shouldLoadUser) { if (isGraphQLEnabled(state)) { await dispatch(loadMe()); @@ -374,8 +374,9 @@ export async function redirectUserToDefaultTeam() { const teamId = LocalStorageStore.getPreviousTeamId(user.id); let myTeams = getMyTeams(state); - if (myTeams.length === 0) { - if (isUserFirstAdmin) { + const teams = getActiveTeamsList(state); + if (teams.length === 0) { + if (isUserFirstAdmin && onboardingFlowEnabled) { getHistory().push('/preparing-workspace'); return; } diff --git a/webapp/channels/src/components/do_verify_email/do_verify_email.tsx b/webapp/channels/src/components/do_verify_email/do_verify_email.tsx index 0e81ead2c7..52390fa461 100644 --- a/webapp/channels/src/components/do_verify_email/do_verify_email.tsx +++ b/webapp/channels/src/components/do_verify_email/do_verify_email.tsx @@ -6,6 +6,7 @@ import {useIntl} from 'react-intl'; import {useSelector, useDispatch} from 'react-redux'; import {useLocation, useHistory} from 'react-router-dom'; +import {redirectUserToDefaultTeam} from 'actions/global_actions'; import {trackEvent} from 'actions/telemetry_actions.jsx'; import LaptopAlertSVG from 'components/common/svg_images_components/laptop_alert_svg'; @@ -14,6 +15,7 @@ import LoadingScreen from 'components/loading_screen'; import {clearErrors, logError} from 'mattermost-redux/actions/errors'; import {verifyUserEmail, getMe} from 'mattermost-redux/actions/users'; +import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {DispatchFunc} from 'mattermost-redux/types/actions'; @@ -38,6 +40,7 @@ const DoVerifyEmail = () => { const token = params.get('token') ?? ''; const loggedIn = Boolean(useSelector(getCurrentUserId)); + const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const [verifyStatus, setVerifyStatus] = useState(VerifyStatus.PENDING); const [serverError, setServerError] = useState(''); @@ -49,11 +52,15 @@ const DoVerifyEmail = () => { const handleRedirect = () => { if (loggedIn) { - // need info about whether admin or not, - // and whether admin has already completed - // first time onboarding. Instead of fetching and orchestrating that here, - // let the default root component handle it. - history.push('/'); + if (onboardingFlowEnabled) { + // need info about whether admin or not, + // and whether admin has already completed + // first time onboarding. Instead of fetching and orchestrating that here, + // let the default root component handle it. + history.push('/'); + return; + } + redirectUserToDefaultTeam(); return; } diff --git a/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/index.ts b/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/index.ts index 5a2ac01c35..80bdf8f328 100644 --- a/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/index.ts +++ b/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/index.ts @@ -8,6 +8,7 @@ import {withRouter} from 'react-router-dom'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {GenericAction} from 'mattermost-redux/types/actions'; import {getCurrentRelativeTeamUrl} from 'mattermost-redux/selectors/entities/teams'; +import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isFirstAdmin} from 'mattermost-redux/selectors/entities/users'; import {getUserGuideDropdownPluginMenuItems} from 'selectors/plugins'; @@ -31,6 +32,7 @@ function mapStateToProps(state: GlobalState) { teamUrl: getCurrentRelativeTeamUrl(state), pluginMenuItems: getUserGuideDropdownPluginMenuItems(state), isFirstAdmin: isFirstAdmin(state), + onboardingFlowEnabled: getIsOnboardingFlowEnabled(state), }; } diff --git a/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/user_guide_dropdown.test.tsx b/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/user_guide_dropdown.test.tsx index aa1ac2e833..ed4e5532b9 100644 --- a/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/user_guide_dropdown.test.tsx +++ b/webapp/channels/src/components/global_header/center_controls/user_guide_dropdown/user_guide_dropdown.test.tsx @@ -34,6 +34,7 @@ describe('components/channel_header/components/UserGuideDropdown', () => { }, pluginMenuItems: [], isFirstAdmin: false, + onboardingFlowEnabled: false, }; test('should match snapshot', () => { diff --git a/webapp/channels/src/components/login/login.tsx b/webapp/channels/src/components/login/login.tsx index edde751e63..f72e7df0f0 100644 --- a/webapp/channels/src/components/login/login.tsx +++ b/webapp/channels/src/components/login/login.tsx @@ -13,7 +13,7 @@ import {UserProfile} from '@mattermost/types/users'; import {Client4} from 'mattermost-redux/client'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; -import {isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; +import {getIsOnboardingFlowEnabled, isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getTeamByName, getMyTeamMember} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; import {isSystemAdmin} from 'mattermost-redux/utils/user_utils'; @@ -104,6 +104,7 @@ const Login = ({onCustomizeHeader}: LoginProps) => { const currentUser = useSelector(getCurrentUser); const experimentalPrimaryTeam = useSelector((state: GlobalState) => (ExperimentalPrimaryTeam ? getTeamByName(state, ExperimentalPrimaryTeam) : undefined)); const experimentalPrimaryTeamMember = useSelector((state: GlobalState) => getMyTeamMember(state, experimentalPrimaryTeam?.id ?? '')); + const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const isCloud = useSelector(isCurrentLicenseCloud); const graphQLEnabled = useSelector(isGraphQLEnabled); @@ -634,12 +635,14 @@ const Login = ({onCustomizeHeader}: LoginProps) => { } else if (experimentalPrimaryTeamMember.team_id) { // Only set experimental team if user is on that team history.push(`/${ExperimentalPrimaryTeam}`); - } else { + } else if (onboardingFlowEnabled) { // need info about whether admin or not, // and whether admin has already completed // first time onboarding. Instead of fetching and orchestrating that here, // let the default root component handle it. history.push('/'); + } else { + redirectUserToDefaultTeam(); } }; diff --git a/webapp/channels/src/components/preparing_workspace/preparing_workspace.tsx b/webapp/channels/src/components/preparing_workspace/preparing_workspace.tsx index 1cfb41e4ea..90f45c3928 100644 --- a/webapp/channels/src/components/preparing_workspace/preparing_workspace.tsx +++ b/webapp/channels/src/components/preparing_workspace/preparing_workspace.tsx @@ -12,6 +12,7 @@ import {sendEmailInvitesToTeamGracefully} from 'mattermost-redux/actions/teams'; import {getFirstAdminSetupComplete as getFirstAdminSetupCompleteAction} from 'mattermost-redux/actions/general'; import {ActionResult} from 'mattermost-redux/types/actions'; import {Team} from '@mattermost/types/teams'; +import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isFirstAdmin} from 'mattermost-redux/selectors/entities/users'; import {getCurrentTeam, getMyTeams} from 'mattermost-redux/selectors/entities/teams'; import {getFirstAdminSetupComplete, getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; @@ -109,6 +110,7 @@ const PreparingWorkspace = (props: Props) => { defaultMessage: 'Something went wrong. Please try again.', }); const isUserFirstAdmin = useSelector(isFirstAdmin); + const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const currentTeam = useSelector(getCurrentTeam); const myTeams = useSelector(getMyTeams); @@ -289,7 +291,7 @@ const PreparingWorkspace = (props: Props) => { }, [submissionState]); const adminRevisitedPage = firstAdminSetupComplete && submissionState === SubmissionStates.Presubmit; - const shouldRedirect = !isUserFirstAdmin || adminRevisitedPage; + const shouldRedirect = !isUserFirstAdmin || adminRevisitedPage || !onboardingFlowEnabled; useEffect(() => { if (shouldRedirect) { diff --git a/webapp/channels/src/components/root/root.tsx b/webapp/channels/src/components/root/root.tsx index 73f78f6af6..3a648347fe 100644 --- a/webapp/channels/src/components/root/root.tsx +++ b/webapp/channels/src/components/root/root.tsx @@ -10,9 +10,10 @@ import classNames from 'classnames'; import {Client4} from 'mattermost-redux/client'; import {rudderAnalytics, RudderTelemetryHandler} from 'mattermost-redux/client/rudder'; import {General} from 'mattermost-redux/constants'; -import {Theme} from 'mattermost-redux/selectors/entities/preferences'; +import {Theme, getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {getCurrentUser, isCurrentUserSystemAdmin, checkIsFirstAdmin} from 'mattermost-redux/selectors/entities/users'; +import {getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams'; import {setUrl} from 'mattermost-redux/actions/general'; import {setSystemEmojis} from 'mattermost-redux/actions/emojis'; @@ -89,8 +90,6 @@ import {ActionResult} from 'mattermost-redux/types/actions'; import WelcomePostRenderer from 'components/welcome_post_renderer'; -import {getMyTeams} from 'mattermost-redux/selectors/entities/teams'; - import {applyLuxonDefaults} from './effects'; import RootProvider from './root_provider'; @@ -360,8 +359,11 @@ export default class Root extends React.PureComponent { return; } - const myTeams = getMyTeams(storeState); - if (myTeams.length > 0) { + const teams = getActiveTeamsList(storeState); + + const onboardingFlowEnabled = getIsOnboardingFlowEnabled(storeState); + + if (teams.length > 0 || !onboardingFlowEnabled) { GlobalActions.redirectUserToDefaultTeam(); return; } diff --git a/webapp/channels/src/components/root/root_redirect/index.ts b/webapp/channels/src/components/root/root_redirect/index.ts index eca15abc20..1bb7912cea 100644 --- a/webapp/channels/src/components/root/root_redirect/index.ts +++ b/webapp/channels/src/components/root/root_redirect/index.ts @@ -6,6 +6,7 @@ import {connect} from 'react-redux'; import {getFirstAdminSetupComplete} from 'mattermost-redux/actions/general'; import {getCurrentUserId, isCurrentUserSystemAdmin, isFirstAdmin} from 'mattermost-redux/selectors/entities/users'; +import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {GenericAction} from 'mattermost-redux/types/actions'; import {GlobalState} from 'types/store'; @@ -13,7 +14,11 @@ import {GlobalState} from 'types/store'; import RootRedirect, {Props} from './root_redirect'; function mapStateToProps(state: GlobalState) { - const isElegibleForFirstAdmingOnboarding = isCurrentUserSystemAdmin(state); + const onboardingFlowEnabled = getIsOnboardingFlowEnabled(state); + let isElegibleForFirstAdmingOnboarding = onboardingFlowEnabled; + if (isElegibleForFirstAdmingOnboarding) { + isElegibleForFirstAdmingOnboarding = isCurrentUserSystemAdmin(state); + } return { currentUserId: getCurrentUserId(state), isElegibleForFirstAdmingOnboarding, diff --git a/webapp/channels/src/components/signup/signup.tsx b/webapp/channels/src/components/signup/signup.tsx index 0075949586..072661e655 100644 --- a/webapp/channels/src/components/signup/signup.tsx +++ b/webapp/channels/src/components/signup/signup.tsx @@ -17,7 +17,7 @@ import {getTeamInviteInfo} from 'mattermost-redux/actions/teams'; import {createUser, loadMe, loadMeREST} from 'mattermost-redux/actions/users'; import {DispatchFunc} from 'mattermost-redux/types/actions'; import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; -import {isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; +import {getIsOnboardingFlowEnabled, isGraphQLEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; import {isEmail} from 'mattermost-redux/utils/helpers'; @@ -25,6 +25,7 @@ import {GlobalState} from 'types/store'; import {getGlobalItem} from 'selectors/storage'; +import {redirectUserToDefaultTeam} from 'actions/global_actions'; import {removeGlobalItem, setGlobalItem} from 'actions/storage'; import {addUserToTeamFromInvite} from 'actions/team_actions'; import {trackEvent} from 'actions/telemetry_actions.jsx'; @@ -103,6 +104,7 @@ const Signup = ({onCustomizeHeader}: SignupProps) => { } = config; const {IsLicensed} = useSelector(getLicense); const loggedIn = Boolean(useSelector(getCurrentUserId)); + const onboardingFlowEnabled = useSelector(getIsOnboardingFlowEnabled); const usedBefore = useSelector((state: GlobalState) => (!inviteId && !loggedIn && token ? getGlobalItem(state, token, null) : undefined)); const graphQLEnabled = useSelector(isGraphQLEnabled); @@ -307,7 +309,15 @@ const Signup = ({onCustomizeHeader}: SignupProps) => { } else if (inviteId) { getInviteInfo(inviteId); } else if (loggedIn) { - history.push('/'); + if (onboardingFlowEnabled) { + // need info about whether admin or not, + // and whether admin has already completed + // first tiem onboarding. Instead of fetching and orchestrating that here, + // let the default root component handle it. + history.push('/'); + } else { + redirectUserToDefaultTeam(); + } } } @@ -450,12 +460,14 @@ const Signup = ({onCustomizeHeader}: SignupProps) => { if (redirectTo) { history.push(redirectTo); - } else { + } else if (onboardingFlowEnabled) { // need info about whether admin or not, // and whether admin has already completed // first tiem onboarding. Instead of fetching and orchestrating that here, // let the default root component handle it. history.push('/'); + } else { + redirectUserToDefaultTeam(); } }; diff --git a/webapp/channels/src/components/terms_of_service/index.ts b/webapp/channels/src/components/terms_of_service/index.ts index c22fba415f..b6e4ec9030 100644 --- a/webapp/channels/src/components/terms_of_service/index.ts +++ b/webapp/channels/src/components/terms_of_service/index.ts @@ -6,6 +6,7 @@ import {bindActionCreators, Dispatch, ActionCreatorsMapObject} from 'redux'; import {getTermsOfService, updateMyTermsOfServiceStatus} from 'mattermost-redux/actions/users'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; +import {getIsOnboardingFlowEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {GlobalState} from '@mattermost/types/store'; import {ActionFunc, GenericAction} from 'mattermost-redux/types/actions'; @@ -25,7 +26,9 @@ type Actions = { function mapStateToProps(state: GlobalState) { const config = getConfig(state); + const onboardingFlowEnabled = getIsOnboardingFlowEnabled(state); return { + onboardingFlowEnabled, termsEnabled: config.EnableCustomTermsOfService === 'true', emojiMap: getEmojiMap(state), }; diff --git a/webapp/channels/src/components/terms_of_service/terms_of_service.test.tsx b/webapp/channels/src/components/terms_of_service/terms_of_service.test.tsx index 5c9f58faab..53e82e5234 100644 --- a/webapp/channels/src/components/terms_of_service/terms_of_service.test.tsx +++ b/webapp/channels/src/components/terms_of_service/terms_of_service.test.tsx @@ -27,6 +27,7 @@ describe('components/terms_of_service/TermsOfService', () => { location: {search: ''}, termsEnabled: true, emojiMap: {} as EmojiMap, + onboardingFlowEnabled: false, }; test('should match snapshot', () => { diff --git a/webapp/channels/src/components/terms_of_service/terms_of_service.tsx b/webapp/channels/src/components/terms_of_service/terms_of_service.tsx index f885830f9c..315808a316 100644 --- a/webapp/channels/src/components/terms_of_service/terms_of_service.tsx +++ b/webapp/channels/src/components/terms_of_service/terms_of_service.tsx @@ -38,6 +38,7 @@ export interface TermsOfServiceProps { ) => {data: UpdateMyTermsOfServiceStatusResponse}; }; emojiMap: EmojiMap; + onboardingFlowEnabled: boolean; } interface TermsOfServiceState { @@ -110,12 +111,14 @@ export default class TermsOfService extends React.PureComponent