From 4eee6295addee2094212226562cc352e1954210f Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 16:34:05 -0700 Subject: [PATCH 01/10] Add basic new page with list --- web-app/src/containers/New/index.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web-app/src/containers/New/index.tsx b/web-app/src/containers/New/index.tsx index 35010d3d..839c2832 100644 --- a/web-app/src/containers/New/index.tsx +++ b/web-app/src/containers/New/index.tsx @@ -6,11 +6,18 @@ interface Props { } const NewPage = (props: Props) => { + const [tutorialList, setTutorialList] = React.useState([{ id: '1', title: 'Demo', description: 'A basic demo' }]) // context return (

Start a new Project

- + {tutorialList.map(tutorial => ( +
+

{tutorial.title}

+

{tutorial.description}

+ +
+ ))}
) } From 5a02b7987e7c2eb39ec2a8fa9d9b13ba75d2f030 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 16:52:59 -0700 Subject: [PATCH 02/10] initialize new tutorial --- src/editor/commands/index.ts | 33 ++++++++++++++++++++++++---- src/editor/index.ts | 2 ++ src/state/actions/index.ts | 19 +++++++++------- src/state/context/tutorials/basic.ts | 2 +- src/state/machine.ts | 3 ++- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/editor/commands/index.ts b/src/editor/commands/index.ts index 9ea0b92e..c6eb5b60 100644 --- a/src/editor/commands/index.ts +++ b/src/editor/commands/index.ts @@ -2,11 +2,15 @@ import * as vscode from 'vscode' import { join } from 'path' import { setStorage } from '../storage' import ReactWebView from '../ReactWebView' +import { isEmptyWorkspace } from '../workspace' import * as CR from 'typings' +// TODO: replace with actual tutorial loading later +import tutorial from '../../state/context/tutorials/basic' const COMMANDS = { START: 'coderoad.start', NEW_OR_CONTINUE: 'coderoad.new_or_continue', + TUTORIAL_LAUNCH: 'coderoad.tutorial_launch', OPEN_WEBVIEW: 'coderoad.open_webview', SEND_STATE: 'coderoad.send_state', SEND_DATA: 'coderoad.send_data', @@ -20,12 +24,13 @@ interface CreateCommandProps { machine: CR.StateMachine, storage: any, git: any + position: any } // React panel webview let webview: any; -export const createCommands = ({ context, machine, storage, git }: CreateCommandProps) => ({ +export const createCommands = ({ context, machine, storage, git, position }: CreateCommandProps) => ({ // initialize [COMMANDS.START]: () => { // set local storage workspace @@ -36,6 +41,11 @@ export const createCommands = ({ context, machine, storage, git }: CreateCommand console.log('webview', webview.panel.webview.postMessage) machine.activate() }, + // open React webview + [COMMANDS.OPEN_WEBVIEW]: (column: number = vscode.ViewColumn.One) => { + webview.createOrShow(column); + }, + // launch with continue or new [COMMANDS.NEW_OR_CONTINUE]: async () => { // verify that the user has a tutorial & progress // verify git is setup with a coderoad remote @@ -51,9 +61,24 @@ export const createCommands = ({ context, machine, storage, git }: CreateCommand // otherwise start from 'NEW' machine.send(canContinue ? 'CONTINUE' : 'NEW') }, - // open React webview - [COMMANDS.OPEN_WEBVIEW]: (column: number = vscode.ViewColumn.One) => { - webview.createOrShow(column); + // launch a new tutorial + [COMMANDS.TUTORIAL_LAUNCH]: async () => { + console.log('launch tutorial') + + await isEmptyWorkspace() + + await git.gitInitIfNotExists() + + // TODO: use actual tutorial repo + await Promise.all([git.gitSetupRemote(tutorial.meta.repo), storage.setTutorial(tutorial), storage.resetProgress()]) + + // TODO: refactor to allow client to call initialization + const pos: CR.Position = await position.getInitial(tutorial) + + // eslint-disable-next-line + const { steps } = tutorial.data + const { setup } = steps[pos.stepId].actions + await git.gitLoadCommits(setup) }, // open a file [COMMANDS.OPEN_FILE]: async (relativeFilePath: string) => { diff --git a/src/editor/index.ts b/src/editor/index.ts index 26504478..57f97bca 100644 --- a/src/editor/index.ts +++ b/src/editor/index.ts @@ -3,6 +3,7 @@ import * as CR from 'typings' import { createCommands } from './commands' import * as storage from '../services/storage' import * as git from '../services/git' +import * as position from '../services/position' interface Props { machine: CR.StateMachine, @@ -33,6 +34,7 @@ class Editor { machine: this.machine, storage, git, + position, }) for (const cmd in commands) { const command: vscode.Disposable = vscode.commands.registerCommand(cmd, commands[cmd]) diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts index c2abb20b..5cf22a7e 100644 --- a/src/state/actions/index.ts +++ b/src/state/actions/index.ts @@ -11,7 +11,17 @@ let initialProgress: CR.Progress = { } export default { - tutorialLoad: assign({ + createWebview() { + console.log('execute coderoad.open_webview') + vscode.commands.executeCommand('coderoad.open_webview') + }, + newOrContinue() { + vscode.commands.executeCommand('coderoad.new_or_continue') + }, + tutorialLaunch() { + vscode.commands.executeCommand('coderoad.tutorial_launch') + }, + tutorialContinue: assign({ // load initial data, progress & position data(): CR.TutorialData { console.log('ACTION: tutorialLoad.data') @@ -45,11 +55,4 @@ export default { return position } }), - createWebview() { - console.log('execute coderoad.open_webview') - vscode.commands.executeCommand('coderoad.open_webview') - }, - newOrContinue() { - vscode.commands.executeCommand('coderoad.new_or_continue') - } } \ No newline at end of file diff --git a/src/state/context/tutorials/basic.ts b/src/state/context/tutorials/basic.ts index 395ac008..81b2c9e6 100644 --- a/src/state/context/tutorials/basic.ts +++ b/src/state/context/tutorials/basic.ts @@ -4,7 +4,7 @@ const basic: CR.Tutorial = { id: 'tutorialId', meta: { version: '0.1.0', - repo: 'https://github.com/ShMcK/coderoad-vscode.git', + repo: 'https://github.com/ShMcK/coderoad-tutorial-basic.git', createdBy: 'shmck', createdAt: 'Sat, 11 May 2019 18:25:24 GMT', updatedBy: 'shmck', diff --git a/src/state/machine.ts b/src/state/machine.ts index 273a915e..82a8065a 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -40,6 +40,7 @@ export const machine = Machine< }, }, InitializeTutorial: { + onEntry: ['tutorialLaunch'], on: { TUTORIAL_LOADED: 'Tutorial' } @@ -48,7 +49,7 @@ export const machine = Machine< }, ContinueTutorial: { - onEntry: 'tutorialLoad', + onEntry: 'tutorialContinue', on: { TUTORIAL_START: { target: 'Tutorial.LoadNext', From 314e71bc2c282867521525a1cbbb8c2a63fb7966 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 17:22:39 -0700 Subject: [PATCH 03/10] setup pages --- package.json | 1 + web-app/src/App.tsx | 21 +---------------- web-app/src/Routes.tsx | 14 ++++++++--- web-app/src/components/Cond/utils/state.ts | 9 +++++++- web-app/src/containers/Continue/index.tsx | 5 ++-- web-app/src/containers/New/index.tsx | 27 +++++++++++++++------- web-app/src/containers/Tutorial/index.tsx | 14 +++++++++++ web-app/src/utils/DataContext.tsx | 22 ++++++++++++++++++ web-app/stories/Continue.stories.tsx | 4 ++-- web-app/stories/New.stories.tsx | 4 ++-- 10 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 web-app/src/containers/Tutorial/index.tsx create mode 100644 web-app/src/utils/DataContext.tsx diff --git a/package.json b/package.json index 4239b431..41f1340b 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "postinstall": "node ./node_modules/vscode/bin/install", + "storybook": "cd web-app && npm run storybook", "test": "npm run build && node ./node_modules/vscode/bin/test" }, "devDependencies": { diff --git a/web-app/src/App.tsx b/web-app/src/App.tsx index 22e7e0a2..f269027d 100644 --- a/web-app/src/App.tsx +++ b/web-app/src/App.tsx @@ -3,31 +3,12 @@ import * as CR from 'typings' import Debugger from './components/Debugger' import Routes from './Routes' +import DataContext, { initialState, initialData} from './utils/DataContext' interface ReceivedEvent { data: CR.Action } -const initialState = { SelectTutorial: 'Initial '} -const initialData: CR.MachineContext = { - position: { levelId: '', stageId: '', stepId: '' }, - data: { - summary: { - title: '', - description: '', - levelList: [], - }, - levels: {}, - stages: {}, - steps: {}, - }, - progress: { levels: {}, stages: {}, steps: {}, complete: false }, -} - -const DataContext = React.createContext({ state: initialState, ...initialData }) - - - const App = () => { const [state, setState] = React.useState(initialState) const [data, setData]: [CR.MachineContext, (data: CR.MachineContext) => void] = React.useState(initialData) diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index 044cd066..fa544ccc 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -1,9 +1,9 @@ import * as React from 'react' -import { send } from './utils/vscode' import Cond from './components/Cond' import NewPage from './containers/New' import ContinuePage from './containers/Continue' +import TutorialPage from './containers/Tutorial' interface Props { @@ -14,11 +14,19 @@ const Routes = ({ state }: Props) => { // TODO: refactor cond to user and accept first route as if/else if return (
+ +
+

Starting...

+
+
- send('TUTORIAL_START')} /> + - console.log('continue!')} tutorials={[]} /> + + + +
) diff --git a/web-app/src/components/Cond/utils/state.ts b/web-app/src/components/Cond/utils/state.ts index 5706cc57..fdf4abf5 100644 --- a/web-app/src/components/Cond/utils/state.ts +++ b/web-app/src/components/Cond/utils/state.ts @@ -1,9 +1,16 @@ export function stateMatch(state: any, statePath: string) { let current = state let paths = statePath.split('.') + let complete = false try { for (const p of paths) { - current = current[p] + if (p === current && !complete) { + // handle strings + complete = true + } else { + // handle objects + current = current[p] + } } } catch (error) { return false diff --git a/web-app/src/containers/Continue/index.tsx b/web-app/src/containers/Continue/index.tsx index 128ed1f7..1c427648 100644 --- a/web-app/src/containers/Continue/index.tsx +++ b/web-app/src/containers/Continue/index.tsx @@ -9,10 +9,11 @@ interface Props { // onReset(): void } -const ContinuePage = (props: Props) => { +export const ContinuePage = (props: Props) => { // context return (
+

Continue

{props.tutorials.map((tutorial: CR.Tutorial) => ( { ) } -export default ContinuePage +export default () => console.log(id)}/> diff --git a/web-app/src/containers/New/index.tsx b/web-app/src/containers/New/index.tsx index 839c2832..faec32e2 100644 --- a/web-app/src/containers/New/index.tsx +++ b/web-app/src/containers/New/index.tsx @@ -1,25 +1,36 @@ import * as React from 'react' import { Button } from '@alifd/next' +import Cond from '../../components/Cond' +import DataContext from '../../utils/DataContext' +import { send } from '../../utils/vscode' interface Props { onNew(tutorialId: string): void } -const NewPage = (props: Props) => { +export const NewPage = (props: Props) => { + const { state } = React.useContext(DataContext) const [tutorialList, setTutorialList] = React.useState([{ id: '1', title: 'Demo', description: 'A basic demo' }]) // context return (
-

Start a new Project

- {tutorialList.map(tutorial => ( +
-

{tutorial.title}

-

{tutorial.description}

- +

Start a new Project

+ {tutorialList.map(tutorial => ( +
+

{tutorial.title}

+

{tutorial.description}

+ +
+ ))}
- ))} +
+ +
Initializing tutorial...
+
) } -export default NewPage +export default () => send('TUTORIAL_START')} /> diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx new file mode 100644 index 00000000..c7d75d5d --- /dev/null +++ b/web-app/src/containers/Tutorial/index.tsx @@ -0,0 +1,14 @@ +import * as React from 'react' + +interface Props {} + +const Tutorial = (props: Props) => { + // useContext + return ( +
+

Tutorial

+
+ ) +} + +export default Tutorial diff --git a/web-app/src/utils/DataContext.tsx b/web-app/src/utils/DataContext.tsx new file mode 100644 index 00000000..490a4c92 --- /dev/null +++ b/web-app/src/utils/DataContext.tsx @@ -0,0 +1,22 @@ +import * as React from 'react' +import * as CR from 'typings' + +export const initialState = { SelectTutorial: 'Initial ' } +export const initialData: CR.MachineContext = { + position: { levelId: '', stageId: '', stepId: '' }, + data: { + summary: { + title: '', + description: '', + levelList: [], + }, + levels: {}, + stages: {}, + steps: {}, + }, + progress: { levels: {}, stages: {}, steps: {}, complete: false }, +} + +const DataContext = React.createContext({ state: initialState, ...initialData }) + +export default DataContext \ No newline at end of file diff --git a/web-app/stories/Continue.stories.tsx b/web-app/stories/Continue.stories.tsx index 1f4df9d0..bfa1b65c 100644 --- a/web-app/stories/Continue.stories.tsx +++ b/web-app/stories/Continue.stories.tsx @@ -3,7 +3,7 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { action } from '@storybook/addon-actions' -import Continue from '../src/containers/Continue' +import { ContinuePage } from '../src/containers/Continue' import demo from './data/basic' -storiesOf('Continue', module).add('Page', () => ) +storiesOf('Continue', module).add('Page', () => ) diff --git a/web-app/stories/New.stories.tsx b/web-app/stories/New.stories.tsx index 5ade6701..f82ef46e 100644 --- a/web-app/stories/New.stories.tsx +++ b/web-app/stories/New.stories.tsx @@ -3,6 +3,6 @@ import React from 'react' import { storiesOf } from '@storybook/react' import { action } from '@storybook/addon-actions' -import New from '../src/containers/New' +import { NewPage } from '../src/containers/New' -storiesOf('New', module).add('Page', () => ) +storiesOf('New', module).add('Page', () => ) From cb9f82ed445814db6b8d81dfde829ee8c571c4b5 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 20:02:13 -0700 Subject: [PATCH 04/10] setup continue path --- src/editor/commands/index.ts | 18 +----------------- src/state/actions/index.ts | 23 +++++++++++++++++++++-- src/state/machine.ts | 2 +- web-app/src/Routes.tsx | 4 ++-- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/editor/commands/index.ts b/src/editor/commands/index.ts index c6eb5b60..b1057581 100644 --- a/src/editor/commands/index.ts +++ b/src/editor/commands/index.ts @@ -9,7 +9,6 @@ import tutorial from '../../state/context/tutorials/basic' const COMMANDS = { START: 'coderoad.start', - NEW_OR_CONTINUE: 'coderoad.new_or_continue', TUTORIAL_LAUNCH: 'coderoad.tutorial_launch', OPEN_WEBVIEW: 'coderoad.open_webview', SEND_STATE: 'coderoad.send_state', @@ -45,23 +44,8 @@ export const createCommands = ({ context, machine, storage, git, position }: Cre [COMMANDS.OPEN_WEBVIEW]: (column: number = vscode.ViewColumn.One) => { webview.createOrShow(column); }, - // launch with continue or new - [COMMANDS.NEW_OR_CONTINUE]: async () => { - // verify that the user has a tutorial & progress - // verify git is setup with a coderoad remote - const [tutorial, progress, hasGit, hasGitRemote] = await Promise.all([ - storage.getTutorial(), - storage.getProgress(), - git.gitVersion(), - git.gitCheckRemoteExists(), - ]) - const canContinue = !!(tutorial && progress && hasGit && hasGitRemote) - console.log('canContinue', canContinue) - // if a tutorial exists, 'CONTINUE' - // otherwise start from 'NEW' - machine.send(canContinue ? 'CONTINUE' : 'NEW') - }, // launch a new tutorial + // NOTE: may be better to move into action as logic is primarily non-vscode [COMMANDS.TUTORIAL_LAUNCH]: async () => { console.log('launch tutorial') diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts index 5cf22a7e..86ede3f6 100644 --- a/src/state/actions/index.ts +++ b/src/state/actions/index.ts @@ -1,6 +1,10 @@ import { assign } from 'xstate' +// NOTE: codesmell - importing machine +import { machine } from '../../extension' import * as CR from 'typings' import * as vscode from 'vscode' +import * as storage from '../../services/storage' +import * as git from '../../services/git' let initialTutorial: CR.Tutorial | undefined let initialProgress: CR.Progress = { @@ -15,8 +19,23 @@ export default { console.log('execute coderoad.open_webview') vscode.commands.executeCommand('coderoad.open_webview') }, - newOrContinue() { - vscode.commands.executeCommand('coderoad.new_or_continue') + async newOrContinue() { + // verify that the user has a tutorial & progress + // verify git is setup with a coderoad remote + const [tutorial, progress, hasGit, hasGitRemote] = await Promise.all([ + storage.getTutorial(), + storage.getProgress(), + git.gitVersion(), + git.gitCheckRemoteExists(), + ]) + const canContinue = !!(tutorial && progress && hasGit && hasGitRemote) + + if (canContinue) { + initialTutorial = tutorial + initialProgress = progress + } + + machine.send(canContinue ? 'CONTINUE' : 'NEW') }, tutorialLaunch() { vscode.commands.executeCommand('coderoad.tutorial_launch') diff --git a/src/state/machine.ts b/src/state/machine.ts index 82a8065a..0ddc3799 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -49,7 +49,7 @@ export const machine = Machine< }, ContinueTutorial: { - onEntry: 'tutorialContinue', + onEntry: ['tutorialContinue'], on: { TUTORIAL_START: { target: 'Tutorial.LoadNext', diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index fa544ccc..ae96cce3 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -15,7 +15,7 @@ const Routes = ({ state }: Props) => { return (
-
+

Starting...

@@ -23,7 +23,7 @@ const Routes = ({ state }: Props) => { - + From 8b6499b143bd0719f4755b56d5400fdccdae4187 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 20:32:53 -0700 Subject: [PATCH 05/10] refactor tutorial paths --- src/editor/commands/index.ts | 4 +-- src/services/api/fetch.ts | 32 ------------------- src/services/api/index.ts | 2 +- src/state/actions/index.ts | 7 ++-- src/state/context/index.ts | 2 +- tsconfig.json | 5 ++- .../context/tutorials => tutorials}/basic.ts | 0 web-app/src/services/api/index.tsx | 32 +++++++++++++++++++ web-app/tsconfig.paths.json | 3 ++ 9 files changed, 47 insertions(+), 40 deletions(-) delete mode 100644 src/services/api/fetch.ts rename {src/state/context/tutorials => tutorials}/basic.ts (100%) create mode 100644 web-app/src/services/api/index.tsx diff --git a/src/editor/commands/index.ts b/src/editor/commands/index.ts index b1057581..f083417d 100644 --- a/src/editor/commands/index.ts +++ b/src/editor/commands/index.ts @@ -4,8 +4,6 @@ import { setStorage } from '../storage' import ReactWebView from '../ReactWebView' import { isEmptyWorkspace } from '../workspace' import * as CR from 'typings' -// TODO: replace with actual tutorial loading later -import tutorial from '../../state/context/tutorials/basic' const COMMANDS = { START: 'coderoad.start', @@ -46,7 +44,7 @@ export const createCommands = ({ context, machine, storage, git, position }: Cre }, // launch a new tutorial // NOTE: may be better to move into action as logic is primarily non-vscode - [COMMANDS.TUTORIAL_LAUNCH]: async () => { + [COMMANDS.TUTORIAL_LAUNCH]: async (tutorial: CR.Tutorial) => { console.log('launch tutorial') await isEmptyWorkspace() diff --git a/src/services/api/fetch.ts b/src/services/api/fetch.ts deleted file mode 100644 index 206ae0eb..00000000 --- a/src/services/api/fetch.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as CR from 'typings' - -// temporary tutorials -import basicTutorial from '../../state/context/tutorials/basic' - -interface Options { - resource: string - params?: any -} - -const tutorialsData: { [key: string]: CR.Tutorial } = { - tutorialId: basicTutorial, -} - -// TODO: replace with fetch resource -export default async function fetch(options: Options): Promise { - console.log('options', options) - switch (options.resource) { - case 'getTutorialsSummary': - // list of ids with summaries - let data: { [id: string]: CR.TutorialSummary } = {} - for (const tutorial of Object.values(tutorialsData)) { - data[tutorial.id] = tutorial.data.summary - } - return data - case 'getTutorial': - // specific tutorial by id - return tutorialsData[options.params.id] - default: - throw new Error('Resource not found') - } -} diff --git a/src/services/api/index.ts b/src/services/api/index.ts index 206ae0eb..efa759dd 100644 --- a/src/services/api/index.ts +++ b/src/services/api/index.ts @@ -1,7 +1,7 @@ import * as CR from 'typings' // temporary tutorials -import basicTutorial from '../../state/context/tutorials/basic' +import basicTutorial from 'tutorials/basic' interface Options { resource: string diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts index 86ede3f6..dd3c4cfa 100644 --- a/src/state/actions/index.ts +++ b/src/state/actions/index.ts @@ -1,6 +1,7 @@ import { assign } from 'xstate' // NOTE: codesmell - importing machine import { machine } from '../../extension' +import api from '../../services/api' import * as CR from 'typings' import * as vscode from 'vscode' import * as storage from '../../services/storage' @@ -37,8 +38,10 @@ export default { machine.send(canContinue ? 'CONTINUE' : 'NEW') }, - tutorialLaunch() { - vscode.commands.executeCommand('coderoad.tutorial_launch') + async tutorialLaunch() { + // TODO: add selection of tutorial id + const tutorial: CR.Tutorial = await api({ resource: 'getTutorial', params: { id: '1' } }) + vscode.commands.executeCommand('coderoad.tutorial_launch', tutorial) }, tutorialContinue: assign({ // load initial data, progress & position diff --git a/src/state/context/index.ts b/src/state/context/index.ts index 3b0443a4..36c3e65e 100644 --- a/src/state/context/index.ts +++ b/src/state/context/index.ts @@ -1,4 +1,4 @@ -import basicTutorialData from './tutorials/basic' +import basicTutorialData from 'tutorials/basic' import * as CR from 'typings' const tutorialContext: CR.MachineContext = { diff --git a/tsconfig.json b/tsconfig.json index cef79727..dd77dd55 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "dom" ], "sourceMap": true, - "rootDir": "src", + "rootDirs": ["src", "tutorials"], "baseUrl": "src", "strict": true, /* enable all strict type-checking options */ /* Additional Checks */ @@ -23,6 +23,9 @@ "emitDecoratorMetadata": true, "paths": { "typings": ["../typings/index.d.ts"], + "tutorials/basic": [ + "../tutorials/basic.ts" + ] }, }, "exclude": [ diff --git a/src/state/context/tutorials/basic.ts b/tutorials/basic.ts similarity index 100% rename from src/state/context/tutorials/basic.ts rename to tutorials/basic.ts diff --git a/web-app/src/services/api/index.tsx b/web-app/src/services/api/index.tsx new file mode 100644 index 00000000..b7bf2875 --- /dev/null +++ b/web-app/src/services/api/index.tsx @@ -0,0 +1,32 @@ +import * as CR from 'typings' + +// temporary tutorials +import basicTutorial from 'tutorials/basic' + +interface Options { + resource: string + params?: any +} + +const tutorialsData: { [key: string]: CR.Tutorial } = { + tutorialId: basicTutorial, +} + +// TODO: replace with fetch resource +export default async function fetch(options: Options): Promise { + console.log('options', options) + switch (options.resource) { + case 'getTutorialsSummary': + // list of ids with summaries + let data: { [id: string]: CR.TutorialSummary } = {} + for (const tutorial of Object.values(tutorialsData)) { + data[tutorial.id] = tutorial.data.summary + } + return data + case 'getTutorial': + // specific tutorial by id + return tutorialsData[options.params.id] + default: + throw new Error('Resource not found') + } +} diff --git a/web-app/tsconfig.paths.json b/web-app/tsconfig.paths.json index 89a64aa3..12e7166b 100644 --- a/web-app/tsconfig.paths.json +++ b/web-app/tsconfig.paths.json @@ -9,6 +9,9 @@ "typings": [ "../../typings/index.d.ts" ], + "tutorials/basic": [ + "../../tutorials/basic.ts" + ] } }, "exclude": [ From 9f435160f578b4e69f443e781bccef846dd16b05 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 20:33:40 -0700 Subject: [PATCH 06/10] remove unused --- src/editor/commands/start-old.ts | 108 ------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 src/editor/commands/start-old.ts diff --git a/src/editor/commands/start-old.ts b/src/editor/commands/start-old.ts deleted file mode 100644 index 5d172fbc..00000000 --- a/src/editor/commands/start-old.ts +++ /dev/null @@ -1,108 +0,0 @@ -import * as vscode from 'vscode' -import * as CR from 'typings' - -import tutorialSetup from '../../services/tutorialSetup' -import { isEmptyWorkspace, openReadme } from '../workspace' -import { setWorkspaceRoot } from '../../services/node' -import { setStorage } from '../../editor/storage' - -/* -new -if current workspace is empty, use it -if not, open a new folder then start -*/ - -// async function continueTutorial() { -// // TODO: verify that tutorial is loaded in workspace -// // TODO: verify progress -// // TODO: verify setup -// await loadProgressPosition() -// await openReadme() -// } - -async function newTutorial(tutorial: CR.Tutorial) { - // if workspace isn't empty, clear it out if given permission - const isEmpty: boolean = await isEmptyWorkspace() - if (!isEmpty) { - // eslint-disable-next-line - const options = ['Open a new folder', 'I\'ll clear the files and folders myself'] - const shouldOpenFolder = await vscode.window.showQuickPick(options) - if (shouldOpenFolder === options[0]) { - await vscode.commands.executeCommand('vscode.openFolder') - } - } - - await tutorialSetup(tutorial) - await openReadme() -} - - -export default async function start(context: vscode.ExtensionContext): Promise { - console.log('start', context) - - - return; - - // const modes = ['New'] - - // const canContinue = await validateCanContinue() - // if (canContinue) { - // modes.push('Continue') - // } - - // const selectedMode: string | undefined = await vscode.window.showQuickPick(modes) - - // if (!selectedMode) { - // throw new Error('No mode selected') - // return - // } - - // interface TutorialQuickPickItem extends vscode.QuickPickItem { - // id: string - // } - - // // load tutorial summaries - // const tutorialsData: { [id: string]: CR.TutorialSummary } = await api({ - // resource: 'getTutorialsSummary', - // }) - // const selectableTutorials: TutorialQuickPickItem[] = Object.keys(tutorialsData).map(id => { - // const tutorial = tutorialsData[id] - // return { - // label: tutorial.title, - // description: tutorial.description, - // // detail: '', // optional additional info - // id, - // } - // }) - // const selectedTutorial: TutorialQuickPickItem | undefined = await vscode.window.showQuickPick(selectableTutorials) - - // if (!selectedTutorial) { - // throw new Error('No tutorial selected') - // } - - // // load specific tutorial - // const tutorial: CR.Tutorial | undefined = await fetch({ - // resource: 'getTutorial', - // params: { id: selectedTutorial.id }, - // }) - - // if (!tutorial) { - // throw new Error('No tutorial found') - // } - - // switch (selectedMode) { - // // new tutorial - // case modes[0]: - // await newTutorial(tutorial) - // break - // // continue - // case modes[1]: - // await continueTutorial() - // break - // } - - // // setup hook to run tests on save - - - // TODO: start -} From 0d1a30a1dd714c4d058072b0facb2ad1da74cc57 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 20:50:27 -0700 Subject: [PATCH 07/10] setup continue page --- src/state/machine.ts | 1 - web-app/src/containers/Continue/index.tsx | 28 +++++++++---------- .../ContinueItem.tsx => New/TutorialItem.tsx} | 4 +-- 3 files changed, 15 insertions(+), 18 deletions(-) rename web-app/src/containers/{Continue/ContinueItem.tsx => New/TutorialItem.tsx} (85%) diff --git a/src/state/machine.ts b/src/state/machine.ts index 0ddc3799..ada2d90b 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -46,7 +46,6 @@ export const machine = Machine< } }, } - }, ContinueTutorial: { onEntry: ['tutorialContinue'], diff --git a/web-app/src/containers/Continue/index.tsx b/web-app/src/containers/Continue/index.tsx index 1c427648..62639ac7 100644 --- a/web-app/src/containers/Continue/index.tsx +++ b/web-app/src/containers/Continue/index.tsx @@ -1,29 +1,27 @@ import * as React from 'react' -import CR from 'typings' - -import ContinueItem from './ContinueItem' +import { send } from '../../utils/vscode' +import DataContext from '../../utils/DataContext' +import { Button, Card } from '@alifd/next' interface Props { - tutorials: CR.Tutorial[] - onContinue(tutorialId: string): void - // onReset(): void + onContinue(): void } export const ContinuePage = (props: Props) => { // context + const { data } = React.useContext(DataContext) return (

Continue

- {props.tutorials.map((tutorial: CR.Tutorial) => ( - props.onContinue(tutorial.id)} - title={tutorial.data.summary.title} - description={tutorial.data.summary.description} - /> - ))} + +
+

{data.summary.title}

+

{data.summary.description}

+ +
+
) } -export default () => console.log(id)}/> +export default () => { send('TUTORIAL_START') }} /> diff --git a/web-app/src/containers/Continue/ContinueItem.tsx b/web-app/src/containers/New/TutorialItem.tsx similarity index 85% rename from web-app/src/containers/Continue/ContinueItem.tsx rename to web-app/src/containers/New/TutorialItem.tsx index 278206a9..6138e706 100644 --- a/web-app/src/containers/Continue/ContinueItem.tsx +++ b/web-app/src/containers/New/TutorialItem.tsx @@ -7,7 +7,7 @@ interface Props { onContinue(): void } -const ContinueItem = (props: Props) => { +const TutorialItem = (props: Props) => { return (
@@ -19,4 +19,4 @@ const ContinueItem = (props: Props) => { ) } -export default ContinueItem +export default TutorialItem From 7f0dd625fb956abf65f539414c7aede092b96493 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 21:11:22 -0700 Subject: [PATCH 08/10] use chart ids --- src/state/machine.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/state/machine.ts b/src/state/machine.ts index ada2d90b..8d8cba43 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -11,7 +11,7 @@ export const machine = Machine< CR.MachineEvent >( { - id: 'tutorial', + id: 'root', context: initialContext, initial: 'SelectTutorial', states: { @@ -42,7 +42,7 @@ export const machine = Machine< InitializeTutorial: { onEntry: ['tutorialLaunch'], on: { - TUTORIAL_LOADED: 'Tutorial' + TUTORIAL_LOADED: '#tutorial' } }, } @@ -50,18 +50,18 @@ export const machine = Machine< ContinueTutorial: { onEntry: ['tutorialContinue'], on: { - TUTORIAL_START: { - target: 'Tutorial.LoadNext', - } + TUTORIAL_START: '#tutorial-load-next' } }, } }, Tutorial: { + id: 'tutorial', initial: 'Summary', states: { LoadNext: { - onEntry: () => send('LOAD_NEXT'), + id: 'tutorial-load-next', + // onEntry: () => send('LOAD_NEXT'), on: { LOAD_NEXT: [ { @@ -144,7 +144,7 @@ export const machine = Machine< cond: 'hasNextLevel', }, { - target: 'EndTutorial', + target: '#root.Tutorial.EndTutorial', }, ], }, From 9ba52b0b332ee0fa30bf4ca891d0e9ce32e64545 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 21:15:44 -0700 Subject: [PATCH 09/10] refactor & remove unused --- src/editor/commands/index.ts | 2 +- src/state/index.ts | 6 ------ src/state/machine.ts | 2 +- src/state/message.ts | 13 ------------- typings/index.d.ts | 1 - 5 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 src/state/message.ts diff --git a/src/editor/commands/index.ts b/src/editor/commands/index.ts index f083417d..f7517e04 100644 --- a/src/editor/commands/index.ts +++ b/src/editor/commands/index.ts @@ -86,6 +86,6 @@ export const createCommands = ({ context, machine, storage, git, position }: Cre }, [COMMANDS.RECEIVE_ACTION]: (action: string | CR.Action) => { console.log('onReceiveAction', action) - machine.onReceive(action) + machine.send(action) } }) \ No newline at end of file diff --git a/src/state/index.ts b/src/state/index.ts index 6a7cb3bb..1dc28042 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -36,12 +36,6 @@ class StateMachine { this.service.stop() } send(action: string | CR.Action) { - console.log('machine.send') - console.log(action) - this.service.send(action) - } - onReceive(action: string | CR.Action) { - console.log(action) this.service.send(action) } } diff --git a/src/state/machine.ts b/src/state/machine.ts index 8d8cba43..6a527c2f 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -61,7 +61,7 @@ export const machine = Machine< states: { LoadNext: { id: 'tutorial-load-next', - // onEntry: () => send('LOAD_NEXT'), + // onEntry: [() => send('LOAD_NEXT')], on: { LOAD_NEXT: [ { diff --git a/src/state/message.ts b/src/state/message.ts deleted file mode 100644 index 571b2100..00000000 --- a/src/state/message.ts +++ /dev/null @@ -1,13 +0,0 @@ -// import panel from '../views/Panel' -import * as CR from 'typings' - -export const onSend = (action: CR.Action) => { - // if (!panel || !panel.currentPanel) { - // throw new Error('No valid panel available') - // } - // panel.currentPanel.postMessage(action) -} - -export const onReceive = (action: CR.Action) => { - console.log(`RECEIVED: ${JSON.stringify(action)}`) -} diff --git a/typings/index.d.ts b/typings/index.d.ts index 044be525..f5771d1a 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -168,5 +168,4 @@ export interface StateMachine { activate(): void deactivate(): void send(action: string | Action): void - onReceive(action: string | Action): void } From 7c2bd8fe65d7975b74d64d81cab0553ccca3040e Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 9 Jun 2019 21:44:39 -0700 Subject: [PATCH 10/10] run formatting --- web-app/.prettierrc.js | 7 ++ web-app/src/App.tsx | 84 +++++++++++------------ web-app/src/Routes.tsx | 40 +++++------ web-app/src/components/Loading/index.tsx | 5 -- web-app/src/containers/Continue/index.tsx | 8 ++- web-app/src/containers/New/index.tsx | 4 +- web-app/src/services/api/index.tsx | 36 +++++----- web-app/src/utils/DataContext.tsx | 2 +- 8 files changed, 96 insertions(+), 90 deletions(-) create mode 100644 web-app/.prettierrc.js diff --git a/web-app/.prettierrc.js b/web-app/.prettierrc.js new file mode 100644 index 00000000..aee180bd --- /dev/null +++ b/web-app/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + printWidth: 120, + semi: false, + singleQuote: true, + tabWidth: 2, + trailingComma: 'all', +} diff --git a/web-app/src/App.tsx b/web-app/src/App.tsx index f269027d..c0e40849 100644 --- a/web-app/src/App.tsx +++ b/web-app/src/App.tsx @@ -3,54 +3,54 @@ import * as CR from 'typings' import Debugger from './components/Debugger' import Routes from './Routes' -import DataContext, { initialState, initialData} from './utils/DataContext' +import DataContext, { initialState, initialData } from './utils/DataContext' interface ReceivedEvent { - data: CR.Action + data: CR.Action } const App = () => { - const [state, setState] = React.useState(initialState) - const [data, setData]: [CR.MachineContext, (data: CR.MachineContext) => void] = React.useState(initialData) - - const handleEvent = (event: ReceivedEvent): void => { - const message = event.data - console.log('RECEIVED') - console.log(message) - // messages from core - if (message.type === 'SET_STATE') { - setState(message.payload.state) - setData(message.payload.data) - } else if (message.type === 'SET_DATA') { - setData(message.payload.data) - } + const [state, setState] = React.useState(initialState) + const [data, setData]: [CR.MachineContext, (data: CR.MachineContext) => void] = React.useState(initialData) + + const handleEvent = (event: ReceivedEvent): void => { + const message = event.data + console.log('RECEIVED') + console.log(message) + // messages from core + if (message.type === 'SET_STATE') { + setState(message.payload.state) + setData(message.payload.data) + } else if (message.type === 'SET_DATA') { + setData(message.payload.data) } - - // event bus listener - React.useEffect(() => { - const listener = 'message' - window.addEventListener(listener, handleEvent) - return () => { - window.removeEventListener(listener, handleEvent) - } - }) - - const value = { - state, - position: data.position, - data: data.data, - progress: data.progress, + } + + // event bus listener + React.useEffect(() => { + const listener = 'message' + window.addEventListener(listener, handleEvent) + return () => { + window.removeEventListener(listener, handleEvent) } - - // TODO: refactor cond to user and accept first route as if/else if - return ( - -
- - -
-
- ) + }) + + const value = { + state, + position: data.position, + data: data.data, + progress: data.progress, + } + + // TODO: refactor cond to user and accept first route as if/else if + return ( + +
+ + +
+
+ ) } -export default App \ No newline at end of file +export default App diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index ae96cce3..c00c56b8 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -1,35 +1,33 @@ import * as React from 'react' +import Loading from './components/Loading' import Cond from './components/Cond' import NewPage from './containers/New' import ContinuePage from './containers/Continue' import TutorialPage from './containers/Tutorial' - interface Props { state: any } const Routes = ({ state }: Props) => { - // TODO: refactor cond to user and accept first route as if/else if - return ( -
- -
-

Starting...

-
-
- - - - - - - - - -
- ) + // TODO: refactor cond to user and accept first route as if/else if + return ( +
+ + + + + + + + + + + + +
+ ) } -export default Routes \ No newline at end of file +export default Routes diff --git a/web-app/src/components/Loading/index.tsx b/web-app/src/components/Loading/index.tsx index 9fd7fb7f..02955315 100644 --- a/web-app/src/components/Loading/index.tsx +++ b/web-app/src/components/Loading/index.tsx @@ -1,11 +1,6 @@ import * as React from 'react' -// import send from '../../data/send' const Loading = () => { - React.useEffect(() => { - // load tutorial and progress on startup - // send({ type: 'GET/TUTORIAL' }) - }) return
Loading...
} diff --git a/web-app/src/containers/Continue/index.tsx b/web-app/src/containers/Continue/index.tsx index 62639ac7..c40ff78b 100644 --- a/web-app/src/containers/Continue/index.tsx +++ b/web-app/src/containers/Continue/index.tsx @@ -24,4 +24,10 @@ export const ContinuePage = (props: Props) => { ) } -export default () => { send('TUTORIAL_START') }} /> +export default () => ( + { + send('TUTORIAL_START') + }} + /> +) diff --git a/web-app/src/containers/New/index.tsx b/web-app/src/containers/New/index.tsx index faec32e2..a8e46992 100644 --- a/web-app/src/containers/New/index.tsx +++ b/web-app/src/containers/New/index.tsx @@ -26,8 +26,8 @@ export const NewPage = (props: Props) => { ))}
- -
Initializing tutorial...
+ +
Initializing tutorial...
) diff --git a/web-app/src/services/api/index.tsx b/web-app/src/services/api/index.tsx index b7bf2875..efa759dd 100644 --- a/web-app/src/services/api/index.tsx +++ b/web-app/src/services/api/index.tsx @@ -4,29 +4,29 @@ import * as CR from 'typings' import basicTutorial from 'tutorials/basic' interface Options { - resource: string - params?: any + resource: string + params?: any } const tutorialsData: { [key: string]: CR.Tutorial } = { - tutorialId: basicTutorial, + tutorialId: basicTutorial, } // TODO: replace with fetch resource export default async function fetch(options: Options): Promise { - console.log('options', options) - switch (options.resource) { - case 'getTutorialsSummary': - // list of ids with summaries - let data: { [id: string]: CR.TutorialSummary } = {} - for (const tutorial of Object.values(tutorialsData)) { - data[tutorial.id] = tutorial.data.summary - } - return data - case 'getTutorial': - // specific tutorial by id - return tutorialsData[options.params.id] - default: - throw new Error('Resource not found') - } + console.log('options', options) + switch (options.resource) { + case 'getTutorialsSummary': + // list of ids with summaries + let data: { [id: string]: CR.TutorialSummary } = {} + for (const tutorial of Object.values(tutorialsData)) { + data[tutorial.id] = tutorial.data.summary + } + return data + case 'getTutorial': + // specific tutorial by id + return tutorialsData[options.params.id] + default: + throw new Error('Resource not found') + } } diff --git a/web-app/src/utils/DataContext.tsx b/web-app/src/utils/DataContext.tsx index 490a4c92..ffee2cfc 100644 --- a/web-app/src/utils/DataContext.tsx +++ b/web-app/src/utils/DataContext.tsx @@ -19,4 +19,4 @@ export const initialData: CR.MachineContext = { const DataContext = React.createContext({ state: initialState, ...initialData }) -export default DataContext \ No newline at end of file +export default DataContext