diff --git a/src/channel/index.ts b/src/channel/index.ts index 64e0c5aa..b19bc650 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -57,7 +57,7 @@ class Channel implements Channel { // new tutorial if (!tutorial || !tutorial.id || !tutorial.version) { - this.send({ type: 'NEW_TUTORIAL' }) + this.send({ type: 'START_NEW_TUTORIAL' }) return } @@ -66,12 +66,12 @@ class Channel implements Channel { if (progress.complete) { // tutorial is already complete - this.send({ type: 'NEW_TUTORIAL' }) + this.send({ type: 'START_NEW_TUTORIAL' }) return } - + console.log('send LOAD_STORED_TUTORIAL') // communicate to client the tutorial & stepProgress state - this.send({ type: 'CONTINUE_TUTORIAL', payload: { tutorial, progress, position } }) + this.send({ type: 'LOAD_STORED_TUTORIAL', payload: { tutorial, progress, position } }) return // clear tutorial local storage diff --git a/typings/index.d.ts b/typings/index.d.ts index 5fe546f8..a6a49333 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -66,18 +66,18 @@ export interface MachineEvent { export interface MachineStateSchema { states: { - Start: { + Setup: { states: { Startup: {} Authenticate: {} Error: {} - NewOrContinue: {} + LoadStoredTutorial: {} + Start: {} SelectTutorial: {} LoadTutorialSummary: {} Summary: {} LoadTutorialData: {} SetupNewTutorial: {} - ContinueTutorial: {} } } Tutorial: { diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index 352bfe91..6ed674c3 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -1,8 +1,8 @@ import * as React from 'react' import useRouter from './components/Router' import Workspace from './components/Workspace' -import ContinuePage from './containers/Continue' -import LoadingPage from './containers/LoadingPage' +import LoadingPage from './containers/Loading' +import StartPage from './containers/Start' import NewPage from './containers/New' import OverviewPage from './containers/Overview' import CompletedPage from './containers/Tutorial/CompletedPage' @@ -13,26 +13,26 @@ const Routes = () => { return ( - {/* Start */} - + {/* Setup */} + - - + + - + - + - + - + - + {/* Tutorial */} diff --git a/web-app/src/containers/LoadingPage.tsx b/web-app/src/containers/Loading/LoadingPage.tsx similarity index 88% rename from web-app/src/containers/LoadingPage.tsx rename to web-app/src/containers/Loading/LoadingPage.tsx index f375034a..8452bbba 100644 --- a/web-app/src/containers/LoadingPage.tsx +++ b/web-app/src/containers/Loading/LoadingPage.tsx @@ -1,8 +1,8 @@ import * as React from 'react' import * as T from 'typings' import { css, jsx } from '@emotion/core' -import Loading from '../components/Loading' -import Message from '../components/Message' +import Loading from '../../components/Loading' +import Message from '../../components/Message' interface Props { text: string diff --git a/web-app/src/containers/Loading/index.tsx b/web-app/src/containers/Loading/index.tsx new file mode 100644 index 00000000..8452bbba --- /dev/null +++ b/web-app/src/containers/Loading/index.tsx @@ -0,0 +1,39 @@ +import * as React from 'react' +import * as T from 'typings' +import { css, jsx } from '@emotion/core' +import Loading from '../../components/Loading' +import Message from '../../components/Message' + +interface Props { + text: string + context: T.MachineContext +} + +const styles = { + page: { + position: 'relative' as 'relative', + display: 'flex', + flexDirection: 'column' as 'column', + alignItems: 'center', + justifyContent: 'center', + width: '100%', + }, +} + +const LoadingPage = ({ text, context }: Props) => { + const { error } = context + if (error) { + return ( +
+ +
+ ) + } + return ( +
+ +
+ ) +} + +export default LoadingPage diff --git a/web-app/src/containers/New/index.tsx b/web-app/src/containers/New/index.tsx index f99a6571..89ec7e1b 100644 --- a/web-app/src/containers/New/index.tsx +++ b/web-app/src/containers/New/index.tsx @@ -4,7 +4,7 @@ import * as T from 'typings' import * as G from 'typings/graphql' import ErrorView from '../../components/Error' import queryTutorials from '../../services/apollo/queries/tutorials' -import LoadingPage from '../LoadingPage' +import LoadingPage from '../Loading' import NewPage from './NewPage' interface ContainerProps { diff --git a/web-app/src/containers/Overview/index.tsx b/web-app/src/containers/Overview/index.tsx index 11ab58ce..aada9a6b 100644 --- a/web-app/src/containers/Overview/index.tsx +++ b/web-app/src/containers/Overview/index.tsx @@ -5,7 +5,7 @@ import * as G from 'typings/graphql' import ErrorView from '../../components/Error' import queryTutorial from '../../services/apollo/queries/tutorial' import OverviewPage from './OverviewPage' -import LoadingPage from '../../containers/LoadingPage' +import LoadingPage from '../Loading' interface PageProps { context: CR.MachineContext diff --git a/web-app/src/containers/Start/index.tsx b/web-app/src/containers/Start/index.tsx new file mode 100644 index 00000000..16f1bcc3 --- /dev/null +++ b/web-app/src/containers/Start/index.tsx @@ -0,0 +1,94 @@ +import * as React from 'react' +import * as CR from 'typings' +import * as G from 'typings/graphql' +import { Badge } from '@alifd/next' +import { css, jsx } from '@emotion/core' +import Button from '../../components/Button' + +const styles = { + page: { + position: 'relative' as 'relative', + display: 'flex' as 'flex', + flexDirection: 'column' as 'column', + width: '100%', + height: window.innerHeight, + }, + header: { + flex: 1, + display: 'flex' as 'flex', + flexDirection: 'column' as 'column', + justifyContent: 'flex-end' as 'flex-end', + alignItems: 'center' as 'center', + fontSize: '1rem', + lineHeight: '1rem', + padding: '1rem', + }, + title: { + fontSize: '3rem', + }, + subtitle: { + fontSize: '1.3rem', + }, + options: { + flex: 1, + backgroundColor: '#EBEBEB', + display: 'flex' as 'flex', + flexDirection: 'column' as 'column', + justifyContent: 'flex-start' as 'flex-start', + alignItems: 'center' as 'center', + padding: '1rem', + }, + betaBadge: { + backgroundColor: '#6a67ce', + color: '#FFFFFF', + }, + buttonContainer: { + margin: '0.5rem', + }, +} + +interface Props { + onContinue(): void + onNew(): void + tutorial?: G.Tutorial +} + +export const StartPage = (props: Props) => ( +
+
+ + CodeRoad  + +

Play Interactive Coding Tutorials in VSCode

+
+ +
+
+ +
+ {props.tutorial && ( +
+ +
+ )} +
+
+) + +interface ContainerProps { + context: CR.MachineContext + send(action: CR.Action | string): void +} + +const StartPageContainer = ({ context, send }: ContainerProps) => { + const tutorial = context.tutorial || undefined + return ( + send('CONTINUE_TUTORIAL')} onNew={() => send('NEW_TUTORIAL')} tutorial={tutorial} /> + ) +} + +export default StartPageContainer diff --git a/web-app/src/services/state/actions/context.ts b/web-app/src/services/state/actions/context.ts index a356722b..c7c3d232 100644 --- a/web-app/src/services/state/actions/context.ts +++ b/web-app/src/services/state/actions/context.ts @@ -15,8 +15,9 @@ const contextActions: ActionFunctionMap = { }, }), // @ts-ignore - continueTutorial: assign({ + storeContinuedTutorial: assign({ tutorial: (context: T.MachineContext, event: T.MachineEvent) => { + console.log('storeContinuedTutorial') return event.payload.tutorial }, progress: (context: T.MachineContext, event: T.MachineEvent) => { diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts index 915c0d0b..fe275717 100644 --- a/web-app/src/services/state/machine.ts +++ b/web-app/src/services/state/machine.ts @@ -16,7 +16,7 @@ export const createMachine = (options: any) => { return Machine( { id: 'root', - initial: 'Start', + initial: 'Setup', context: { error: null, env: { machineId: '', sessionId: '', token: '' }, @@ -31,7 +31,7 @@ export const createMachine = (options: any) => { testStatus: null, }, states: { - Start: { + Setup: { initial: 'Startup', states: { Startup: { @@ -46,7 +46,7 @@ export const createMachine = (options: any) => { Authenticate: { invoke: { src: services.authenticate, - onDone: 'NewOrContinue', + onDone: 'LoadStoredTutorial', onError: { target: 'Error', actions: assign({ @@ -56,14 +56,23 @@ export const createMachine = (options: any) => { }, }, Error: {}, - NewOrContinue: { + LoadStoredTutorial: { onEntry: ['loadStoredTutorial'], on: { - CONTINUE_TUTORIAL: { - target: 'ContinueTutorial', - actions: ['continueTutorial'], + LOAD_STORED_TUTORIAL: { + target: 'Start', + actions: ['storeContinuedTutorial'], }, + START_NEW_TUTORIAL: 'Start', + }, + }, + Start: { + on: { NEW_TUTORIAL: 'SelectTutorial', + CONTINUE_TUTORIAL: { + target: '#tutorial-level', + actions: ['continueConfig'], + }, }, }, SelectTutorial: { @@ -123,15 +132,6 @@ export const createMachine = (options: any) => { TUTORIAL_CONFIGURED: '#tutorial', }, }, - ContinueTutorial: { - on: { - TUTORIAL_START: { - target: '#tutorial-level', - actions: ['continueConfig'], - }, - TUTORIAL_SELECT: 'SelectTutorial', - }, - }, }, }, Tutorial: { diff --git a/web-app/stories/Loading.stories.tsx b/web-app/stories/Loading.stories.tsx index f49fa6c2..84693146 100644 --- a/web-app/stories/Loading.stories.tsx +++ b/web-app/stories/Loading.stories.tsx @@ -1,6 +1,6 @@ import { storiesOf } from '@storybook/react' import React from 'react' -import LoadingPage from '../src/containers/LoadingPage' +import LoadingPage from '../src/containers/Loading' import SideBarDecorator from './utils/SideBarDecorator' storiesOf('Components', module) diff --git a/web-app/stories/New.stories.tsx b/web-app/stories/New.stories.tsx index e3900f97..6cd3f587 100644 --- a/web-app/stories/New.stories.tsx +++ b/web-app/stories/New.stories.tsx @@ -23,7 +23,7 @@ const tutorialList = [ }, ] -storiesOf('Start', module) +storiesOf('Select Tutorial', module) .addDecorator(SideBarDecorator) .add('New Page', () => { return diff --git a/web-app/stories/Start.stories.tsx b/web-app/stories/Start.stories.tsx new file mode 100644 index 00000000..91b29c1e --- /dev/null +++ b/web-app/stories/Start.stories.tsx @@ -0,0 +1,33 @@ +import { storiesOf } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import React from 'react' +import { css, jsx } from '@emotion/core' +import SideBarDecorator from './utils/SideBarDecorator' +import StartPage from '../src/containers/Start' + +const styles = { + container: {}, +} + +storiesOf('Start', module) + .addDecorator(SideBarDecorator) + .add('New', () => { + return ( +
+ +
+ ) + }) + .add('Continue', () => { + const tutorial = { + summary: { + title: 'Tutorial Title', + summary: 'Tutorial Summary', + }, + } + return ( +
+ +
+ ) + })