Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
[MM-27526] Onboarding Flow for End Users (#6296)
Browse files Browse the repository at this point in the history
* [MM-26468][MM-26483] Progress Bar Common Component/Sidebar Next Steps Component (#5865)

* [MM-26483] Progress bar common component and PoC in the sidebar

* Styling for the sidebar element and some tests

* Added translations

* Snapshot update

* Style changes

* Use same border design as channels

* [MM-26465] Background and general layout for cloud onboarding (#5823)

* WIP

* WIP

* [MM-26465] Background and general layout for cloud onboarding

* Mobile view, lint and type fixes, added a test file for later use

* More test fixes

* UX feedback

* Replaced dumb comment with useful one

* Turn off graphic at 1020px

* Lint fix

* Update copy

* PR feedback

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>

* [MM-26480] Card/Accordion Common Component (#5861)

* WIP

* WIP

* [MM-26465] Background and general layout for cloud onboarding

* Mobile view, lint and type fixes, added a test file for later use

* More test fixes

* UX feedback

* Replaced dumb comment with useful one

* Turn off graphic at 1020px

* WIP

* Initial card style

* Collapse functionality (no animation)

* WIP

* Rest of accordion common component and some animation

* Lint, type and test fixes

* Updated snapshot

* Reduce nesting

* Merge'd

* PR feedback

* Fix box-shadow on collapsed state

* [MM-26470] Base Next Step Wizard Controller and Styling (#5893)

* WIP

* WIP

* [MM-26465] Background and general layout for cloud onboarding

* Mobile view, lint and type fixes, added a test file for later use

* More test fixes

* UX feedback

* Replaced dumb comment with useful one

* Turn off graphic at 1020px

* WIP

* Initial card style

* Collapse functionality (no animation)

* WIP

* Rest of accordion common component and some animation

* Lint, type and test fixes

* Updated snapshot

* Reduce nesting

* WIP - Wiring for step wizard

* Skip getting started link, hook for final page

* Moved steps into its own constants file, type and test fixes

* Shifted around the screen changing and added final screen placeholder

* Translations and wizard navigation button styling

* Pick starting step based on which are finished, button styling fixes

* Allow for getting out of next steps view by switching channels

* PR feedback

* PR feedback

* blank

* Change style of complete card header to be more like the regular one

* Fixed background on complete step

* Merge'd

* PR feedback

* PR feedback

* Removed translation

* Fixed box shadow transition on card

* Removed duplicate logic

* PR feedback

* PR feedback

* Fixed hover state on completed cards

* re-add margin on complete state

* [MM-26466] Close Next Steps Modal and functionality (#5995)

* Hooked up the sidebar next steps bar and some fixes

* Integration of state into app for next steps view, close next steps view modal preliminary

* Styling and help arrow for modal

* Missed a translation

* PR feedback

* Center the next steps modal

* PR feedback

* Translation fix

* Screen transitions for loading screen and final screen

* Transition screen

* Fixed APNG issue

* Style for desktop and mobile

* Fixed styling

* More fixes

* Functionality and test fixes

* Dev PR feedback

* UX PR feedback

* [MM-27164] Picture Selector Common Component (#5973)

* WIP

* WIP

* [MM-26465] Background and general layout for cloud onboarding

* Mobile view, lint and type fixes, added a test file for later use

* More test fixes

* UX feedback

* Replaced dumb comment with useful one

* Turn off graphic at 1020px

* WIP

* Initial card style

* Collapse functionality (no animation)

* WIP

* Rest of accordion common component and some animation

* Lint, type and test fixes

* Updated snapshot

* Reduce nesting

* WIP - Wiring for step wizard

* Skip getting started link, hook for final page

* Moved steps into its own constants file, type and test fixes

* Shifted around the screen changing and added final screen placeholder

* Translations and wizard navigation button styling

* Pick starting step based on which are finished, button styling fixes

* Allow for getting out of next steps view by switching channels

* PR feedback

* PR feedback

* blank

* Change style of complete card header to be more like the regular one

* Fixed background on complete step

* Merge'd

* PR feedback

* PR feedback

* Removed translation

* Fixed box shadow transition on card

* Removed duplicate logic

* WIP

* Functional component that works

* Styling and a couple tweaks

* A few tests

* Snapshots

* Type and i18n fixes

* PR feedback and test fixes

* Added button hover states

* PR feedback

* Blur select button on select image

* Blur on click, not on select image

* Update components/picture_selector.tsx

Co-authored-by: Nev Angelova <nevyana.angelova@mattermost.com>

Co-authored-by: Nev Angelova <nevyana.angelova@mattermost.com>

* [MM-26482] Textbox Common Component for Cloud Onboarding (#5904)

* WIP

* WIP

* [MM-26465] Background and general layout for cloud onboarding

* Mobile view, lint and type fixes, added a test file for later use

* More test fixes

* UX feedback

* Replaced dumb comment with useful one

* Turn off graphic at 1020px

* WIP

* Initial card style

* Collapse functionality (no animation)

* WIP

* Rest of accordion common component and some animation

* Lint, type and test fixes

* Updated snapshot

* Reduce nesting

* WIP - Wiring for step wizard

* Skip getting started link, hook for final page

* Moved steps into its own constants file, type and test fixes

* Shifted around the screen changing and added final screen placeholder

* Translations and wizard navigation button styling

* Pick starting step based on which are finished, button styling fixes

* Allow for getting out of next steps view by switching channels

* PR feedback

* WIP

* [MM-26472] Textbox Common Component for Cloud Onboarding

* Specific styling for the Cloud Onboarding components

* Added info component and some other styling

* Fixed the error styling

* Fixed most of the shifting in the textbox

* Lint fix

* PR feedback

* blank

* PR feedback

* Change style of complete card header to be more like the regular one

* Fixed background on complete step

* Merge'd

* PR feedback

* PR feedback

* Removed translation

* PR feedback

* Use box shadow instead of border for changing text input

* Improved CSS from Asaad

* Removed inner border when focused/error state

* Removed unnecessary commented code

* Merge'd

* Switch to proper BEM

* Adding a card for opening and setting preferences

* Adding files

* [MM-26469] Complete Profile Step (#6077)

* [MM-26469] Complete Profile Step

* Lint fix

* [MM-26473] Tips and Next Steps screen (#6020)

* Screen transitions for loading screen and final screen

* Transition screen

* Fixed APNG issue

* Style for desktop and mobile

* Fixed styling

* More fixes

* Functionality and test fixes

* Dev PR feedback

* UX PR feedback

* UX feedback

* Merge'd

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>

* [MM-26471] Team Profile Setup step (#6083)

* [MM-26471] Team Profile Setup step

* Translation fix

* PR feedback

* Fixed an issue with an older version of the styles

* Removed commented code

* [MM-26472] Invite Members step (#6143)

* WIP

* WIP

* [MM-26742] Functionality for Invite Members step, and most of styling

* Beginning of common component, currently for use only in the Invite Members step

* Cleanup

* Couple small style fixes

* Fixed the invite link at the bottom

* Lint and test fixes

* PR feedback

* Fixed button width for copy link and fixed test

* [MM-27908] Updated Cloud Logo (#6190)

* [MM-27908] Updated Cloud Logo

* Remove extra prop

* Type fix

* [MM-27907] Fixed input focus colour and fixed placeholder focus on multi_input (#6182)

* [MM-27907] Fixed input focus colour and fixed placeholder focus on multi_input

* PR feedback

* [MM-27159] Button States for Cloud Onboarding (#6189)

* [MM-27159] Button States

* PR feedback

* [MM-27305] Card Component Refactor for smoothness  (#6172)

* Refactor Card component to be more responsive and robust

* Cleanup and a couple other bug fixes

* [MM-27974] Unit Tests for Cloud Onboarding (#6208)

* [MM-27974] Unit Tests for Cloud Onboarding

* Translation fix

* [MM-27923] Turn on Cloud Onboarding for Cloud-only instances (#6225)

* Flow working, pre cleanup, pre merge of Devin's work

* Code clean up

* Adding tests for my added components

* Put package-lock back to master

* Fix bug that always redirects you to the next steps page

* Change function name to avoid confusion

* Code clean up, and this dang package-lock

* Fix one of the test issues

* Fix other tests

* fix alignment of body text in text_card_with_action component

* Fix a few issues in PR review

* pushing to get help

* Fixes and updating tests

* Fix package-lock

* Fix package-lock

* Remove package-lock changes

* Increase transition time from 1 second to 3 seconds

* Some fixes for UX

* add 2 tests to be sure that step filter logic is working based on user roles

* Fix tests

* Fix test

Co-authored-by: Devin Binnie <52460000+devinbinnie@users.noreply.github.com>
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Devin Binnie <devin.binnie@mattermost.com>
Co-authored-by: Nev Angelova <nevyana.angelova@mattermost.com>
  • Loading branch information
5 people authored and jfrerich committed Oct 23, 2020
1 parent 11ce393 commit 29c96ac
Show file tree
Hide file tree
Showing 24 changed files with 639 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ exports[`components/next_steps_view should match snapshot 1`] = `
</div>
<NextStepsTips
animating={false}
isAdmin={true}
showFinalScreen={false}
stopAnimating={[Function]}
/>
Expand Down
6 changes: 5 additions & 1 deletion components/next_steps_view/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import {bindActionCreators, Dispatch} from 'redux';

import {savePreferences} from 'mattermost-redux/actions/preferences';
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';

import {setShowNextStepsView} from 'actions/views/next_steps';
import {GlobalState} from 'types/store';
import {Preferences} from 'utils/constants';

import {getSteps} from './steps';

import NextStepsView from './next_steps_view';

function makeMapStateToProps() {
Expand All @@ -20,7 +22,9 @@ function makeMapStateToProps() {
return (state: GlobalState) => {
return {
currentUser: getCurrentUser(state),
isAdmin: isCurrentUserSystemAdmin(state),
preferences: getCategory(state, Preferences.RECOMMENDED_NEXT_STEPS),
steps: getSteps(state),
};
};
}
Expand Down
62 changes: 60 additions & 2 deletions components/next_steps_view/next_steps_tips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import * as UserAgent from 'utils/user_agent';
import {ModalIdentifiers} from 'utils/constants';
import * as Utils from 'utils/utils';

import TeamMembersModal from 'components/team_members_modal';
import {toggleShortcutsModal} from 'actions/global_actions.jsx';

const seeAllApps = () => {
window.open('https://mattermost.com/download/#mattermostApps', '_blank');
};
Expand Down Expand Up @@ -73,13 +76,17 @@ const openAuthPage = (page: string) => {
browserHistory.push(`/admin_console/authentication/${page}`);
};

export default function NextStepsTips(props: {showFinalScreen: boolean; animating: boolean; stopAnimating: () => void}) {
export default function NextStepsTips(props: { showFinalScreen: boolean; animating: boolean; stopAnimating: () => void; isAdmin: boolean}) {
const dispatch = useDispatch();
const openPluginMarketplace = openModal({modalId: ModalIdentifiers.PLUGIN_MARKETPLACE, dialogType: MarketplaceModal});
const openMoreChannels = openModal({modalId: ModalIdentifiers.MORE_CHANNELS, dialogType: MoreChannels});
const openViewMembersModal = openModal({
modalId: ModalIdentifiers.TEAM_MEMBERS,
dialogType: TeamMembersModal,
});

let nonMobileTips;
if (!Utils.isMobile()) {
if (!Utils.isMobile() && props.isAdmin) {
nonMobileTips = (
<>
<Card expanded={true}>
Expand Down Expand Up @@ -146,6 +153,57 @@ export default function NextStepsTips(props: {showFinalScreen: boolean; animatin
</Card>
</>
);
} else if (!Utils.isMobile() && !props.isAdmin) {
nonMobileTips = (
<>
<Card expanded={true}>
<div className='Card__body'>
<h3>
<FormattedMessage
id='next_steps_view.tips.configureLogins'
defaultMessage='See who else is here'
/>
</h3>
<FormattedMessage
id='next_steps_view.tips.configureLogin.texts'
defaultMessage='Browse or search through the team members directory'
/>
<button
className='NextStepsView__button NextStepsView__finishButton primary'
onClick={() => openViewMembersModal(dispatch)}
>
<FormattedMessage
id='next_steps_view.tips.viewMembers'
defaultMessage='View team members'
/>
</button>
</div>
</Card>
<Card expanded={true}>
<div className='Card__body'>
<h3>
<FormattedMessage
id='next_steps_view.tips.addPluginss'
defaultMessage='Learn Keyboard Shortcuts'
/>
</h3>
<FormattedMessage
id='next_steps_view.tips.addPlugins.texts'
defaultMessage='Work more efficiently with Keyboard Shortcuts in Mattermost.'
/>
<button
className='NextStepsView__button NextStepsView__finishButton primary'
onClick={toggleShortcutsModal}
>
<FormattedMessage
id='next_steps_view.tips.addPlugins.buttons'
defaultMessage='See shortcuts'
/>
</button>
</div>
</Card>
</>
);
}

let downloadSection;
Expand Down
2 changes: 1 addition & 1 deletion components/next_steps_view/next_steps_view.scss
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@
display: flex;
border: none;
background: none;
padding: 12px;
padding: 13px;
width: 100%;

> span {
Expand Down
51 changes: 27 additions & 24 deletions components/next_steps_view/next_steps_view.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,31 @@ import {shallow, ShallowWrapper} from 'enzyme';
import NextStepsView from 'components/next_steps_view/next_steps_view';
import {TestHelper} from 'utils/test_helper';

jest.mock('components/next_steps_view/steps', () => ({
Steps: [
{
id: 'step_1',
title: 'Step_1',
component: jest.fn(),
},
{
id: 'step_2',
title: 'Step_2',
component: jest.fn(),
},
{
id: 'step_3',
title: 'Step_3',
component: jest.fn(),
},
],
}));

describe('components/next_steps_view', () => {
const baseProps = {
steps: [
{
id: 'step_1',
roles: [],
title: 'Step_1',
component: jest.fn(),
},
{
id: 'step_2',
title: 'Step_2',
roles: [],
component: jest.fn(),
},
{
id: 'step_3',
title: 'Step_3',
roles: [],
component: jest.fn(),
},
],
currentUser: TestHelper.getUserMock(),
preferences: [],
isAdmin: true,
actions: {
setShowNextStepsView: jest.fn(),
savePreferences: jest.fn(),
Expand Down Expand Up @@ -74,14 +75,14 @@ describe('components/next_steps_view', () => {
expect(setExpanded).toBeCalledWith('step_2');
});

test('should go to final screen when last step is marked complete', () => {
test('should go to first incomplete step when last step is marked complete', () => {
const wrapper: ShallowWrapper<any, any, NextStepsView> = shallow(
<NextStepsView {...baseProps}/>,
);

wrapper.instance().transitionToFinalScreen = jest.fn();
wrapper.instance().nextStep(jest.fn(), 'step_3');
expect(wrapper.instance().transitionToFinalScreen).toBeCalled();
const setExpanded = jest.fn();
wrapper.instance().nextStep(setExpanded, 'step_3');
expect(setExpanded).toBeCalledWith('step_1');
});

test('should cascade through all steps when all marked complete', () => {
Expand All @@ -108,13 +109,15 @@ describe('components/next_steps_view', () => {
},
],
};
jest.useFakeTimers();

const wrapper: ShallowWrapper<any, any, NextStepsView> = shallow(
<NextStepsView {...props}/>,
);

wrapper.instance().transitionToFinalScreen = jest.fn();
wrapper.instance().nextStep(jest.fn(), 'step_1');
jest.runOnlyPendingTimers();
expect(wrapper.instance().transitionToFinalScreen).toBeCalled();
});
});
53 changes: 37 additions & 16 deletions components/next_steps_view/next_steps_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ import Card from 'components/card/card';
import loadingIcon from 'images/spinner-48x48-blue.apng';
import {Preferences} from 'utils/constants';

import {Steps, StepType} from './steps';
import {StepType} from './steps';
import './next_steps_view.scss';
import NextStepsTips from './next_steps_tips';
import OnboardingBgSvg from './images/onboarding-bg-svg';
import GettingStartedSvg from './images/getting-started-svg';
import CloudLogoSvg from './images/cloud-logo-svg';
import OnboardingSuccessSvg from './images/onboarding-success-svg';

const TRANSITION_SCREEN_TIMEOUT = 1000;
const TRANSITION_SCREEN_TIMEOUT = 3000;

type Props = {
currentUser: UserProfile;
preferences: PreferenceType[];
isAdmin: boolean;
steps: StepType[];
actions: {
savePreferences: (userId: string, preferences: PreferenceType[]) => void;
setShowNextStepsView: (show: boolean) => void;
Expand All @@ -51,13 +53,21 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
}

getStartingStep = () => {
for (let i = 0; i < Steps.length; i++) {
if (!this.isStepComplete(Steps[i].id)) {
return Steps[i].id;
for (let i = 0; i < this.props.steps.length; i++) {
if (!this.isStepComplete(this.props.steps[i].id)) {
return this.props.steps[i].id;
}
}
return this.props.steps[0].id;
}

return Steps[0].id;
getIncompleteStep = () => {
for (let i = 0; i < this.props.steps.length; i++) {
if (!this.isStepComplete(this.props.steps[i].id)) {
return this.props.steps[i].id;
}
}
return null;
}

onSkip = (setExpanded: (expandedKey: string) => void) => {
Expand All @@ -67,8 +77,8 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
}

onFinish = (setExpanded: (expandedKey: string) => void) => {
return (id: string) => {
this.props.actions.savePreferences(this.props.currentUser.id, [{
return async (id: string) => {
await this.props.actions.savePreferences(this.props.currentUser.id, [{
category: Preferences.RECOMMENDED_NEXT_STEPS,
user_id: this.props.currentUser.id,
name: id,
Expand Down Expand Up @@ -100,13 +110,23 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
}

nextStep = (setExpanded: (expandedKey: string) => void, id: string) => {
const currentIndex = Steps.findIndex((step) => step.id === id);
if ((currentIndex + 1) > (Steps.length - 1)) {
this.transitionToFinalScreen();
} else if (this.isStepComplete(Steps[currentIndex + 1].id)) {
this.nextStep(setExpanded, Steps[currentIndex + 1].id);
const currentIndex = this.props.steps.findIndex((step) => step.id === id);
if (currentIndex + 1 > this.props.steps.length - 1) {
// Check if previous steps were skipped before moving on
const incompleteStep = this.getIncompleteStep();
if (incompleteStep === null) {
// Collapse all accordion tiles
setExpanded('');
setTimeout(() => {
this.transitionToFinalScreen();
}, 300);
} else {
setExpanded(incompleteStep);
}
} else if (this.isStepComplete(this.props.steps[currentIndex + 1].id)) {
this.nextStep(setExpanded, this.props.steps[currentIndex + 1].id);
} else {
setExpanded(Steps[currentIndex + 1].id);
setExpanded(this.props.steps[currentIndex + 1].id);
}
}

Expand Down Expand Up @@ -186,7 +206,7 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
}

renderMainBody = () => {
const renderedSteps = Steps.map(this.renderStep);
const renderedSteps = this.props.steps.map(this.renderStep);

return (
<div
Expand Down Expand Up @@ -216,7 +236,7 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
</header>
<div className='NextStepsView__body'>
<div className='NextStepsView__body-main'>
<Accordion defaultExpandedKey={this.getStartingStep()}>
<Accordion defaultExpandedKey={this.getIncompleteStep() === null ? '' : this.getStartingStep()}>
{(setExpanded, expandedKey) => {
return (
<>
Expand Down Expand Up @@ -258,6 +278,7 @@ export default class NextStepsView extends React.PureComponent<Props, State> {
showFinalScreen={this.state.showFinalScreen}
animating={this.state.animating}
stopAnimating={this.stopAnimating}
isAdmin={this.props.isAdmin}
/>
</section>
);
Expand Down
Loading

0 comments on commit 29c96ac

Please sign in to comment.