From 8761cfa0d3c6c3bdec6ce0b72e6d68d7c0782285 Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 15:53:14 -0700
Subject: [PATCH 1/6] log key bindings on ctrl+enter

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 package.json           | 7 +++++++
 src/editor/commands.ts | 4 ++++
 2 files changed, 11 insertions(+)

diff --git a/package.json b/package.json
index f36bf62f..c110096a 100644
--- a/package.json
+++ b/package.json
@@ -78,6 +78,13 @@
         "title": "Start",
         "category": "CodeRoad"
       }
+    ],
+    "keybindings": [
+      {
+        "key": "ctrl+enter",
+        "mac": "ctrl+enter",
+        "command": "coderoad.enter"
+      }
     ]
   },
   "displayName": "CodeRoad",
diff --git a/src/editor/commands.ts b/src/editor/commands.ts
index 2ba69a70..ba08d260 100644
--- a/src/editor/commands.ts
+++ b/src/editor/commands.ts
@@ -12,6 +12,7 @@ export const COMMANDS = {
   CONFIG_TEST_RUNNER: 'coderoad.config_test_runner',
   RUN_TEST: 'coderoad.run_test',
   SET_CURRENT_POSITION: 'coderoad.set_current_position',
+  ENTER: 'coderoad.enter',
 }
 
 interface CreateCommandProps {
@@ -103,5 +104,8 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
       logger('currentPosition', currentPosition)
       testRunner({ position: currentPosition, onSuccess: callbacks?.onSuccess, subtasks })
     },
+    [COMMANDS.ENTER]: () => {
+      console.log('KEY: ctrl+enter')
+    },
   }
 }

From 367da8c0f7bf8267615c041adadf32bfcaabed24 Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 20:45:02 -0700
Subject: [PATCH 2/6] run test on hot key enter

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 src/editor/commands.ts                | 2 +-
 web-app/src/services/state/machine.ts | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/editor/commands.ts b/src/editor/commands.ts
index ba08d260..a7ab6915 100644
--- a/src/editor/commands.ts
+++ b/src/editor/commands.ts
@@ -105,7 +105,7 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
       testRunner({ position: currentPosition, onSuccess: callbacks?.onSuccess, subtasks })
     },
     [COMMANDS.ENTER]: () => {
-      console.log('KEY: ctrl+enter')
+      webview.send({ type: 'KEY_PRESS_ENTER' })
     },
   }
 }
diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts
index 76195e31..7d1bef1e 100644
--- a/web-app/src/services/state/machine.ts
+++ b/web-app/src/services/state/machine.ts
@@ -171,6 +171,9 @@ export const createMachine = (options: any) => {
                     RUN_RESET: {
                       actions: ['runReset'],
                     },
+                    KEY_PRESS_ENTER: {
+                      actions: ['runTest'],
+                    },
                   },
                 },
                 TestRunning: {

From ca2d77eda834a382d9139ca79451a82152dd7086 Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 21:05:29 -0700
Subject: [PATCH 3/6] open continue on success

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 web-app/src/Routes.tsx                        |  2 +-
 .../Tutorial/components/Continue.tsx          |  3 ++-
 web-app/src/containers/Tutorial/index.tsx     | 21 +++++++++++++++----
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx
index 2753a653..7f1ca97e 100644
--- a/web-app/src/Routes.tsx
+++ b/web-app/src/Routes.tsx
@@ -40,7 +40,7 @@ const Routes = () => {
         <LoadingPage text="Loading Level..." processes={context.processes} />
       </Route>
       <Route paths={{ Tutorial: { Level: true } }}>
-        <TutorialPage send={send} context={context} />
+        <TutorialPage send={send} context={context} state={route.replace('Tutorial.Level.', '')} />
       </Route>
       {/* Completed */}
       <Route paths={{ Tutorial: { Completed: true } }}>
diff --git a/web-app/src/containers/Tutorial/components/Continue.tsx b/web-app/src/containers/Tutorial/components/Continue.tsx
index 0667fb39..20c222ad 100644
--- a/web-app/src/containers/Tutorial/components/Continue.tsx
+++ b/web-app/src/containers/Tutorial/components/Continue.tsx
@@ -20,11 +20,12 @@ interface Props {
   title: string
   current: number // level index
   max: number // level count
+  defaultOpen: boolean
   onContinue(): void
 }
 
 const Continue = (props: Props) => {
-  const [modalState, setModalState] = React.useState<'closed' | 'open'>('closed')
+  const [modalState, setModalState] = React.useState<'closed' | 'open'>(props.defaultOpen ? 'open' : 'closed')
 
   const onClose = () => {
     setModalState('closed')
diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx
index bac17481..5d7c8358 100644
--- a/web-app/src/containers/Tutorial/index.tsx
+++ b/web-app/src/containers/Tutorial/index.tsx
@@ -11,7 +11,6 @@ import TestMessage from '../../components/TestMessage'
 import StepProgress from './components/StepProgress'
 import { DISPLAY_RUN_TEST_BUTTON } from '../../environment'
 import formatLevels from './formatLevels'
-// import SettingsPage from './containers/Settings'
 import Reset from './components/Reset'
 import Continue from './components/Continue'
 
@@ -69,6 +68,7 @@ const styles = {
 interface PageProps {
   context: T.MachineContext
   send(action: T.Action): void
+  state: string // 'Normal' | 'TestRunning' | 'TestFail' | 'TestPass' | 'LevelComplete'
 }
 
 /**
@@ -111,6 +111,8 @@ const TutorialPage = (props: PageProps) => {
     testStatus,
   })
 
+  const disableOptions = processes.length > 0 && props.state === 'TestRunning'
+
   return (
     <div>
       <div>
@@ -141,7 +143,7 @@ const TutorialPage = (props: PageProps) => {
         {/* Left */}
         <div css={{ flex: 1 }}>
           {DISPLAY_RUN_TEST_BUTTON && level.status !== 'COMPLETE' ? (
-            <Button style={{ marginLeft: '1rem' }} type="primary" onClick={onRunTest} disabled={processes.length > 0}>
+            <Button style={{ marginLeft: '1rem' }} type="primary" onClick={onRunTest} disabled={disableOptions}>
               Run
             </Button>
           ) : null}
@@ -149,18 +151,29 @@ const TutorialPage = (props: PageProps) => {
 
         {/* Center */}
         <div css={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
-          <Reset onReset={onReset} disabled={processes.length > 0} />
+          <Reset onReset={onReset} disabled={disableOptions} />
         </div>
 
         {/* Right */}
         <div css={{ flex: 1, display: 'flex', justifyContent: 'flex-end' }}>
-          {level.status === 'COMPLETE' || !level.steps.length ? (
+          {!level.steps.length ? (
+            <div css={{ marginRight: '0.5rem' }}>
+              <Continue
+                onContinue={onContinue}
+                current={levelIndex + 1}
+                max={levels.length}
+                title={tutorial.summary.title}
+                defaultOpen={false}
+              />
+            </div>
+          ) : props.state === 'LevelComplete' ? (
             <div css={{ marginRight: '0.5rem' }}>
               <Continue
                 onContinue={onContinue}
                 current={levelIndex + 1}
                 max={levels.length}
                 title={tutorial.summary.title}
+                defaultOpen={true}
               />
             </div>
           ) : level.steps.length > 1 ? (

From 11fbb68fe89ea550362c3ab59563750e1e562b7b Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 21:20:56 -0700
Subject: [PATCH 4/6] disable reset when level complete

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 web-app/src/containers/Tutorial/index.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx
index 5d7c8358..34df4d62 100644
--- a/web-app/src/containers/Tutorial/index.tsx
+++ b/web-app/src/containers/Tutorial/index.tsx
@@ -151,7 +151,7 @@ const TutorialPage = (props: PageProps) => {
 
         {/* Center */}
         <div css={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
-          <Reset onReset={onReset} disabled={disableOptions} />
+          <Reset onReset={onReset} disabled={disableOptions || props.state === 'LevelComplete'} />
         </div>
 
         {/* Right */}

From 9976f58fd1f10fcd6b59adecce28bf29f063a553 Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 21:34:47 -0700
Subject: [PATCH 5/6] hot key to continue (ctrl + enter)

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 web-app/src/containers/Tutorial/components/Continue.tsx | 9 +++++++--
 web-app/src/containers/Tutorial/index.tsx               | 3 ---
 web-app/src/services/state/actions/context.ts           | 7 +++++++
 web-app/src/services/state/machine.ts                   | 6 +++++-
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/web-app/src/containers/Tutorial/components/Continue.tsx b/web-app/src/containers/Tutorial/components/Continue.tsx
index 20c222ad..19451990 100644
--- a/web-app/src/containers/Tutorial/components/Continue.tsx
+++ b/web-app/src/containers/Tutorial/components/Continue.tsx
@@ -1,5 +1,5 @@
 import * as React from 'react'
-import { Dialog } from '@alifd/next'
+import { Dialog, Icon } from '@alifd/next'
 import { css, jsx } from '@emotion/core'
 import Button from '../../../components/Button'
 import ProgressPie from './ProgressPie'
@@ -14,6 +14,9 @@ const styles = {
   message: {
     textAlign: 'center' as 'center',
   },
+  buttonSubtext: {
+    padding: '0.5rem',
+  },
 }
 
 interface Props {
@@ -58,8 +61,10 @@ const Continue = (props: Props) => {
             <h3>{props.title}</h3>
             <br />
             <Button type="primary" size="large" onClick={onContinue}>
-              Continue
+              Continue&nbsp;&nbsp;
+              <Icon type="arrow-right" />
             </Button>
+            <div css={styles.buttonSubtext}>(ctrl + enter)</div>
           </div>
         </div>
       </Dialog>
diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx
index 34df4d62..3c18ee10 100644
--- a/web-app/src/containers/Tutorial/index.tsx
+++ b/web-app/src/containers/Tutorial/index.tsx
@@ -85,9 +85,6 @@ const TutorialPage = (props: PageProps) => {
   const onContinue = (): void => {
     props.send({
       type: 'NEXT_LEVEL',
-      payload: {
-        levelId: position.levelId,
-      },
     })
   }
 
diff --git a/web-app/src/services/state/actions/context.ts b/web-app/src/services/state/actions/context.ts
index 6c6a25f9..a2971e7a 100644
--- a/web-app/src/services/state/actions/context.ts
+++ b/web-app/src/services/state/actions/context.ts
@@ -118,6 +118,13 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
       return event.payload
     },
   }),
+  // @ts-ignore
+  updateLevel: assign({
+    position: (context: T.MachineContext, event: T.MachineEvent): any => {
+      const levelId = context.position.levelId
+      return { levelId }
+    },
+  }),
   loadNext: send(
     (context: T.MachineContext): T.Action => {
       const { position, progress } = context
diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts
index 7d1bef1e..4e62e6db 100644
--- a/web-app/src/services/state/machine.ts
+++ b/web-app/src/services/state/machine.ts
@@ -220,7 +220,11 @@ export const createMachine = (options: any) => {
                   on: {
                     NEXT_LEVEL: {
                       target: 'LoadNext',
-                      actions: ['testClear', 'updatePosition'],
+                      actions: ['testClear', 'updateLevel'],
+                    },
+                    KEY_PRESS_ENTER: {
+                      target: 'LoadNext',
+                      actions: ['testClear', 'updateLevel'],
                     },
                   },
                 },

From 10dbe7fd9615a20ac2993a18d1ec5471d09886f4 Mon Sep 17 00:00:00 2001
From: shmck <shawn.j.mckay@gmail.com>
Date: Fri, 17 Jul 2020 21:37:36 -0700
Subject: [PATCH 6/6] set run button as default

Signed-off-by: shmck <shawn.j.mckay@gmail.com>
---
 web-app/src/containers/Tutorial/index.tsx | 2 +-
 web-app/src/environment.ts                | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx
index 3c18ee10..3e784fa2 100644
--- a/web-app/src/containers/Tutorial/index.tsx
+++ b/web-app/src/containers/Tutorial/index.tsx
@@ -108,7 +108,7 @@ const TutorialPage = (props: PageProps) => {
     testStatus,
   })
 
-  const disableOptions = processes.length > 0 && props.state === 'TestRunning'
+  const disableOptions = processes.length > 0 || props.state === 'TestRunning'
 
   return (
     <div>
diff --git a/web-app/src/environment.ts b/web-app/src/environment.ts
index 05515c12..4b0234c9 100644
--- a/web-app/src/environment.ts
+++ b/web-app/src/environment.ts
@@ -14,4 +14,4 @@ export const TUTORIAL_LIST_URL: string = process.env.REACT_APP_TUTORIAL_LIST_URL
 export const SENTRY_DSN: string | null = process.env.REACT_APP_SENTRY_DSN || null
 
 // config variables
-export const DISPLAY_RUN_TEST_BUTTON = (process.env.CODEROAD_DISPLAY_RUN_TEST_BUTTON || '').toLowerCase() === 'true'
+export const DISPLAY_RUN_TEST_BUTTON = (process.env.CODEROAD_DISPLAY_RUN_TEST_BUTTON || 'true').toLowerCase() === 'true'