Skip to content

Commit

Permalink
Merge pull request #572 from LiskHQ/63-onboarding
Browse files Browse the repository at this point in the history
Implement onboarding - Closes #63
  • Loading branch information
gina contrino authored Mar 28, 2018
2 parents 8aefa42 + 4c6d29a commit e71449c
Show file tree
Hide file tree
Showing 16 changed files with 914 additions and 34 deletions.
30 changes: 30 additions & 0 deletions i18n/locales/en/common.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
" Make sure that you are using the latest version of Lisk Hub.": " Make sure that you are using the latest version of Lisk Hub.",
"About": "About",
"Access extra features": "Access extra features",
"Account initialization": "Account initialization",
"Account locked!": "Account locked!",
"Activity": "Activity",
Expand All @@ -9,6 +10,7 @@
"Additional fee": "Additional fee",
"Address": "Address",
"Address timeout in": "Address timeout in",
"After 10 minutes of not using your passphrase,\n // your Lisk ID will be locked to prevent an unauthorized use of your Lisk ID. .\n // The timer will reset as soon as you make an transaction.\n // After 5 minutes, you can also reset the timer by clicking on \"reset\".": "After 10 minutes of not using your passphrase,\n // your Lisk ID will be locked to prevent an unauthorized use of your Lisk ID. .\n // The timer will reset as soon as you make an transaction.\n // After 5 minutes, you can also reset the timer by clicking on \"reset\".",
"All": "All",
"Amount (LSK)": "Amount (LSK)",
"An error occurred while creating the transaction.": "An error occurred while creating the transaction.",
Expand All @@ -23,9 +25,14 @@
"Blockchain Application Registration": "Blockchain Application Registration",
"Buy Lisk": "Buy Lisk",
"Cancel": "Cancel",
"Change account settings, enable delegate voting and repeat the onboarding here.": "Change account settings, enable delegate voting and repeat the onboarding here.",
"Check for updates...": "Check for updates...",
"Click here to go to the main page of Lisk Hub and find all relevant statistics and ID information": "Click here to go to the main page of Lisk Hub and find all relevant statistics and ID information",
"Click here to skip": "Click here to skip",
"Click here to transfer funds between Lisk IDs and access your transaction history.": "Click here to transfer funds between Lisk IDs and access your transaction history.",
"Close": "Close",
"Coming soon.": "Coming soon.",
"Complete": "Complete",
"Confirm": "Confirm",
"Confirm (Fee: 1 LSK)": "Confirm (Fee: 1 LSK)",
"Confirm (Fee: {{fee}} LSK)": "Confirm (Fee: {{fee}} LSK)",
Expand Down Expand Up @@ -53,6 +60,7 @@
"Delegate features": "Delegate features",
"Delegate name": "Delegate name",
"Delegate section will be displayed.": "Delegate section will be displayed.",
"Delegate voting": "Delegate voting",
"Delegates": "Delegates",
"Discard": "Discard",
"Done": "Done",
Expand All @@ -65,6 +73,7 @@
"Enter your passphrase": "Enter your passphrase",
"Entered passphrase does not belong to the active account": "Entered passphrase does not belong to the active account",
"Error": "Error",
"Explore the network": "Explore the network",
"Explorer": "Explorer",
"Failed to connect to node": "Failed to connect to node",
"Failed to connect: Node {{address}} is not active": "Failed to connect: Node {{address}} is not active",
Expand All @@ -73,9 +82,11 @@
"Final confirmation": "Final confirmation",
"Get to your Dashboard": "Get to your Dashboard",
"Go back to Dashboard": "Go back to Dashboard",
"Go to \"More\" on your Sidebar to start the onboarding whenever you need.": "Go to \"More\" on your Sidebar to start the onboarding whenever you need.",
"Got it": "Got it",
"Great!\nYou’re almost finished": "Great!\nYou’re almost finished",
"Help": "Help",
"Here you see your address and balance. You can click your account avatar to see all your saved IDs.": "Here you see your address and balance. You can click your account avatar to see all your saved IDs.",
"Hide passphrase": "Hide passphrase",
"I am responsible for keeping my passphrase safe. No one can reset it, not even Lisk.": "I am responsible for keeping my passphrase safe. No one can reset it, not even Lisk.",
"I confirm (Fee: 5 LSK)": "I confirm (Fee: 5 LSK)",
Expand All @@ -89,6 +100,7 @@
"Invalid amount": "Invalid amount",
"It is recommended that you initialize your Lisk ID.": "It is recommended that you initialize your Lisk ID.",
"Keep it": "Keep it",
"Keep the overview": "Keep the overview",
"LSK received": "LSK received",
"LSK/BTC": "LSK/BTC",
"Language": "Language",
Expand All @@ -109,6 +121,7 @@
"Log in": "Log in",
"Main menu": "Main menu",
"Mainnet": "Mainnet",
"Manage your application": "Manage your application",
"Maximum of 101 votes in total": "Maximum of 101 votes in total",
"Maximum of {{maxcount}} votes at a time": "Maximum of {{maxcount}} votes at a time",
"Menu": "Menu",
Expand All @@ -126,6 +139,7 @@
"Note: After registration completes,": "Note: After registration completes,",
"Ok": "Ok",
"Okay": "Okay",
"Onboarding whenever you need": "Onboarding whenever you need",
"Out": "Out",
"Outgoing": "Outgoing",
"Page not found.": "Page not found.",
Expand All @@ -152,6 +166,7 @@
"Register": "Register",
"Register 2nd passphrase": "Register 2nd passphrase",
"Register Second Passphrase": "Register Second Passphrase",
"Register and oversee your decentralized application here. Available soon.": "Register and oversee your decentralized application here. Available soon.",
"Register as delegate": "Register as delegate",
"Reload": "Reload",
"Remove": "Remove",
Expand All @@ -171,6 +186,7 @@
"Select the missing words to confirm": "Select the missing words to confirm",
"Selection": "Selection",
"Send": "Send",
"Send LSK": "Send LSK",
"Send Lisk from Blockchain Application": "Send Lisk from Blockchain Application",
"Send Lisk to Blockchain Application": "Send Lisk to Blockchain Application",
"Send to Address": "Send to Address",
Expand All @@ -183,10 +199,15 @@
"Sidechains will revolutionize the way decentralised apps are developed. Here you will be able to find hosts, and monitor your sidechains soon.": "Sidechains will revolutionize the way decentralised apps are developed. Here you will be able to find hosts, and monitor your sidechains soon.",
"Sign in": "Sign in",
"Sorry": "Sorry",
"Start": "Start",
"Start here": "Start here",
"Start the onboarding": "Start the onboarding",
"Start the tour": "Start the tour",
"Submit": "Submit",
"Success": "Success",
"Success!": "Success!",
"Take a quick tour to see how the Lisk Hub works.": "Take a quick tour to see how the Lisk Hub works.",
"Take a tour to see how it works. It should not take longer than 5 minutes": "Take a tour to see how it works. It should not take longer than 5 minutes",
"Testnet": "Testnet",
"Thank you": "Thank you",
"The Wallet will show your recent transactions.": "The Wallet will show your recent transactions.",
Expand All @@ -197,6 +218,7 @@
"This is not reversible.": "This is not reversible.",
"This is your Lisk ID": "This is your Lisk ID",
"This process should take only 10 seconds but may take up to 15 minutes.": "This process should take only 10 seconds but may take up to 15 minutes.",
"Timeout": "Timeout",
"Toggle full screen": "Toggle full screen",
"Total": "Total",
"Total incl. {{fee}} LSK Fee": "Total incl. {{fee}} LSK Fee",
Expand All @@ -213,22 +235,29 @@
"Update download finished": "Update download finished",
"Update now": "Update now",
"Updates downloaded, application has to be restarted to apply the updates.": "Updates downloaded, application has to be restarted to apply the updates.",
"Use Lisk Hub": "Use Lisk Hub",
"Username": "Username",
"Version": "Version",
"View": "View",
"View all the transactions happening on the Lisk Network in real time. Search for addresses and transactions.": "View all the transactions happening on the Lisk Network in real time. Search for addresses and transactions.",
"View forging delegates and vote for the ones you support.": "View forging delegates and vote for the ones you support.",
"Vote_noun": "Vote",
"Vote_verb": "Vote",
"Voted": "Voted",
"Votes": "Votes",
"Votes submitted": "Votes submitted",
"Wallet": "Wallet",
"Welcome to Lisk Hub": "Welcome to Lisk Hub",
"What is Lisk ID?": "What is Lisk ID?",
"What's New...": "What's New...",
"Window": "Window",
"Yes! It's safe": "Yes! It's safe",
"You are looking into a saved account. In order to {{nextAction}} you need to enter your passphrase.": "You are looking into a saved account. In order to {{nextAction}} you need to enter your passphrase.",
"You can also press ↲ enter to search": "You can also press ↲ enter to search",
"You can always get it back.": "You can always get it back.",
"You can now use Lisk Hub.<br": {
" If you want to repeat the onboarding, navigate to \"More\" on the sidebar.": "You can now use Lisk Hub.<br> If you want to repeat the onboarding, navigate to \"More\" on the sidebar."
},
"You have already registered as a delegate.": "You have already registered as a delegate.",
"You only need to do this once for each Lisk ID.": "You only need to do this once for each Lisk ID.",
"You will need it to use your Lisk ID, like sending and voting. You are responsible for keeping your second passphrase safe. No one can restore it, not even Lisk.": "You will need it to use your Lisk ID, like sending and voting. You are responsible for keeping your second passphrase safe. No one can restore it, not even Lisk.",
Expand All @@ -240,6 +269,7 @@
"Your registration is secured on the blockchain.": "Your registration is secured on the blockchain.",
"Your second passphrase registration is being processed and will be confirmed.": "Your second passphrase registration is being processed and will be confirmed.",
"You’re votes are being processed and will be confirmed. It may take up to 10 minutes to be secured in the blockchain.": "You’re votes are being processed and will be confirmed. It may take up to 10 minutes to be secured in the blockchain.",
"You’ve completed the tour!": "You’ve completed the tour!",
"Zero not allowed": "Zero not allowed",
"by moving your mouse.": "by moving your mouse.",
"by tilting your device.": "by tilting your device.",
Expand Down
2 changes: 2 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ module.exports = function (config) {
'src/components/authenticate/index.js',
'src/components/authenticate/authenticate.js',
'src/components/multiStep/index.js',
'src/components/onboarding/index.js',
'src/components/onboarding/steps.js',
'src/components/passphrase/create/index.js',
'src/components/passphrase/createSecond/index.js',
'src/components/passphrase/safekeeping/index.js',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"react-css-themr": "=2.1.2",
"react-dom": "=16.2.0",
"react-i18next": "=6.0.6",
"react-joyride": "1.11.4",
"react-redux": "5.0.6",
"react-router": "4.2.0",
"react-router-dom": "4.2.2",
Expand Down
1 change: 1 addition & 0 deletions src/components/app/global.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import './variables.css';
@import '../onboarding/onboarding.css';

/*****************************************
Expand Down
14 changes: 12 additions & 2 deletions src/components/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,32 @@ import OfflineWrapper from '../offlineWrapper';
import offlineStyle from '../offlineWrapper/offlineWrapper.css';
import AccountVisualDemo from '../accountVisual/demo';
import routes from '../../constants/routes';
import Onboarding from '../onboarding';

class App extends React.Component {
markAsLoaded() {
this.main.classList.add(styles.loaded);
this.main.classList.add('appLoaded');
this.appLoaded = true;
}

startOnboarding() {
this.onboarding.setState({ start: true });
}

render() {
return (
<OfflineWrapper>
<Onboarding appLoaded={this.appLoaded} ref={(el) => {
if (el) { this.onboarding = el.getWrappedInstance().getWrappedInstance(); }
}} />
<main className={`${styles.bodyWrapper}`} ref={(el) => { this.main = el; }}>
<MainMenu />
<MainMenu startOnboarding={this.startOnboarding.bind(this)}/>
<Route path={routes.accounts.path} component={SavedAccounts} />
<section>
<div className={styles.mainBox}>
<Header />
<Header/>
<div id='onboardingAnchor'></div>
<Switch>
<PrivateRoutes path={routes.main.path} render={ ({ match }) => (
<main className={offlineStyle.disableWhenOffline}>
Expand Down
35 changes: 19 additions & 16 deletions src/components/header/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,26 @@ class Header extends React.Component {
<small> LSK</small>
</div>
<CopyToClipboard value={this.props.account.address} className={`${styles.address} account-information-address`}/>
{this.props.autoLog ? <div className={styles.timer}>
{((this.props.account.expireTime &&
{this.props.autoLog
? <div className={`${styles.timer} account-timer`}>
{((this.props.account.expireTime &&
this.props.account.expireTime !== 0) &&
this.props.account.passphrase) ?
<div>
{this.props.t('Address timeout in')} <i> </i>
<Countdown
date={this.props.account.expireTime}
renderer={CountDownTemplate}
onComplete={() => {
this.props.removeSavedAccountPassphrase();
}
}
/>
</div> : <div></div>}
</div>
: <div className={styles.timer}>
this.props.account.passphrase)
?
<div>
{this.props.t('Address timeout in')} <i> </i>
<Countdown
date={this.props.account.expireTime}
renderer={CountDownTemplate}
onComplete={() => {
this.props.removeSavedAccountPassphrase();
}
}
/>
</div>
: <div></div>}
</div>
: <div className={`${styles.timer} account-timer`}>
{this.props.account.passphrase ? '' : <span>
<FontIcon value='locked' className={styles.lock}/> {this.props.t('Account locked!')}
</span>
Expand Down
5 changes: 4 additions & 1 deletion src/components/mainMenu/mainMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ class MainMenu extends React.Component {
/>)}
</ToolboxTabs>
</div>
<Setting showSetting={this.state.setting} />
<Setting showSetting={this.state.setting}
menuToggle={this.menuToggle.bind(this)}
startOnboarding={this.props.startOnboarding}
/>
</Drawer>
</div>
</aside>
Expand Down
124 changes: 124 additions & 0 deletions src/components/onboarding/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React from 'react';
import { connect } from 'react-redux';
import { translate } from 'react-i18next';
import Joyride from 'react-joyride';
import throttle from 'lodash.throttle';
import { FontIcon } from '../fontIcon';
import { steps } from './steps';
import breakpoints from './../../constants/breakpoints';

class Onboarding extends React.Component {
constructor(props) {
super(props);

this.onboardingStarted = false;
this.isAlreadyOnboarded = window.localStorage.getItem('onboarding') === 'false';

this.state = {
isDesktop: window.innerWidth > breakpoints.m,
start: false,
intro: true,
skip: false,
steps: [],
};
}

componentWillReceiveProps(nextProps) {
if ((nextProps.appLoaded && !this.stepsAdded)
|| this.props.showDelegates !== nextProps.showDelegates) {
this.addSteps(nextProps.showDelegates);
}
}

componentDidMount() {
window.addEventListener('resize', throttle(this.resizeWindow.bind(this), 1000));

if (this.props.appLoaded) {
this.addSteps(this.props.showDelegates);
}
}

componentWillUnmount() {
window.removeEventListener('resize', this.resizeWindow.bind(this));
}

resizeWindow() {
this.setState({ isDesktop: window.innerWidth > breakpoints.m });
}

addSteps(showDelegates) {
let newSteps = steps(this.props.t);
if (!showDelegates) {
newSteps = newSteps.filter(step => step.selector !== '#voting');
}

this.setState({ steps: newSteps });
this.stepsAdded = true;
}

reset() {
this.isAlreadyOnboarded = true;
this.onboardingStarted = false;
this.setState({ start: false, intro: true, skip: false });
}

onboardingCallback(data) {
// index 0 is the step you will see when you skip the onboarding
const onboardingNotStarted = data.index === 0 && !this.onboardingStarted;
const onboardingStarted = data.index === 1;
const onboardingStep = data.index > 1;
const skipOnboarding = data.action === 'skip';
const onboardingFinished = data.type === 'finished';

if (onboardingNotStarted) {
this.joyride.next(); // skip to welcome step
}
if (onboardingStarted) {
this.onboardingFinished = false;
this.onboardingStarted = true;
}
if (onboardingStep) {
this.setState({ intro: false });
}
if (skipOnboarding) {
this.setState({ skip: true });
this.joyride.reset(true); // go to step 0 to show the skip step
}
if (onboardingFinished) {
if (this.onboardingFinished) this.reset();
this.onboardingFinished = true;
window.localStorage.setItem('onboarding', 'false');
}
}

render() {
const { isDesktop, start, skip, intro } = this.state;
if (!isDesktop && start) this.setState({ start: false });

return <Joyride
ref={(el) => { this.joyride = el; }}
steps={this.state.steps}
run={this.props.isAuthenticated && isDesktop && (start || !this.isAlreadyOnboarded)}
locale={{
last: (<span>{this.props.t('Complete')}</span>),
skip: skip ? <span>{this.props.t('Use Lisk Hub')}</span> : <span>{this.props.t('Click here to skip')}</span>,
next: intro ? <span>{this.props.t('Start the tour')}</span> : <span>{this.props.t('Next')} <FontIcon value='arrow-right'/></span>,
}}
callback={this.onboardingCallback.bind(this)}
showOverlay={true}
showSkipButton={true}
autoStart={true}
type='continuous'
holePadding={0}
/>;
}
}


const mapStateToProps = state => ({
isAuthenticated: !!state.account.publicKey,
showDelegates: state.settings.advancedMode,
});

export default connect(mapStateToProps, null, null, { withRef: true })(translate(null,
{ withRef: true })(Onboarding));
Loading

0 comments on commit e71449c

Please sign in to comment.