10000 tutorialModel progress · coderoad/coderoad-vscode@57675e5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 57675e5

Browse files
committed
tutorialModel progress
1 parent 97b878a commit 57675e5

File tree

11 files changed

+489
-467
lines changed
  • services
  • state
  • typings
  • 11 files changed

    +489
    -467
    lines changed

    src/editor/commands/index.ts

    Lines changed: 10 additions & 14 deletions
    Original file line numberDiff line numberDiff line change
    @@ -22,11 +22,9 @@ const COMMANDS = {
    2222
    }
    2323

    2424
    interface CreateCommandProps {
    25-
    context: vscode.ExtensionContext
    25+
    vscodeExt: vscode.ExtensionContext
    2626
    machine: CR.StateMachine
    27-
    storage: any
    2827
    git: any
    29-
    position: any
    3028
    }
    3129

    3230
    const resetLayout = () => {
    @@ -36,7 +34,7 @@ const resetLayout = () => {
    3634 F438
    })
    3735
    }
    3836

    39-
    export const createCommands = ({context, machine, storage, git, position}: CreateCommandProps) => {
    37+
    export const createCommands = ({vscodeExt, machine, git}: CreateCommandProps) => {
    4038
    // React panel webview
    4139
    let webview: any
    4240

    @@ -55,10 +53,10 @@ export const createCommands = ({context, machine, storage, git, position}: Creat
    5553
    webviewState = 'RESTARTING'
    5654
    }
    5755

    58-
    setStorage(context.workspaceState)
    56+
    setStorage(vscodeExt.workspaceState)
    5957

    6058
    // activate machine
    61-
    webview = new ReactWebView(context.extensionPath)
    59+
    webview = new ReactWebView(vscodeExt.extensionPath)
    6260
    if (webviewState === 'INITIALIZING') {
    6361
    machine.activate()
    6462
    } else if (webviewState === 'RESTARTING') {
    @@ -80,32 +78,30 @@ export const createCommands = ({context, machine, storage, git, position}: Creat
    8078
    },
    8179
    // launch a new tutorial
    8280
    // NOTE: may be better to move into action as logic is primarily non-vscode
    83-
    [COMMANDS.TUTORIAL_LAUNCH]: async (tutorial: G.Tutorial) => {
    81+
    [COMMANDS.TUTORIAL_LAUNCH]: async (repo: G.TutorialRepo) => {
    8482
    console.log('launch tutorial')
    8583

    8684
    await isEmptyWorkspace()
    8785

    8886
    await git.gitInitIfNotExists()
    8987

    90-
    if (!tutorial.repo || !tutorial.repo.uri) {
    88+
    if (!repo || !repo.uri) {
    9189
    throw new Error('Tutorial repo uri not found')
    9290
    }
    9391

    94-
    // TODO: use actual tutorial repo
    95-
    await Promise.all([git.gitSetupRemote(tutorial.repo.uri), storage.setTutorial(tutorial), storage.resetProgress()])
    92+
    await git.gitSetupRemote(repo.uri)
    9693

    9794
    machine.send('TUTORIAL_LOADED' 10000 )
    9895
    },
    99-
    [COMMANDS.TUTORIAL_SETUP]: async (tutorial: G.Tutorial) => {
    96+
    [COMMANDS.TUTORIAL_SETUP]: async (codingLanguage: G.EnumCodingLanguage) => {
    10097

    10198
    // TODO: allow multiple coding languages in a tutorial
    102-
    console.log('tutorial setup', tutorial)
    99+
    103100
    // setup onSave hook
    104-
    const languageId = tutorial.codingLanguage
    105101
    // console.log(`languageIds: ${languageIds.join(', ')}`)
    106102
    vscode.workspace.onDidSaveTextDocument((document: vscode.TextDocument) => {
    107103
    console.log('save document', document)
    108-
    if (document.uri.scheme === 'file' && languageId === document.languageId) {
    104+
    if (document.uri.scheme === 'file' && codingLanguage === document.languageId) {
    109105
    // do work
    110106
    machine.send('TEST_RUN')
    111107
    }

    src/editor/commands/loadSolution.ts

    Lines changed: 26 additions & 15 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,21 +1,32 @@
    11
    import * as CR from 'typings'
    2+
    import * as G from 'typings/graphql'
    23
    import * as storage from '../../services/storage'
    3-
    import { gitLoadCommits, gitClear } from '../../services/git'
    4+
    import {gitLoadCommits, gitClear} from '../../services/git'
    45

    56
    export default async function loadSolution(dispatch: CR.EditorDispatch): Promise<void> {
    6-
    const [position, tutorial]: [CR.Position, CR.Tutorial | undefined] = await Promise.all([
    7-
    storage.getPosition(),
    8-
    storage.getTutorial(),
    9-
    ])
    10-
    if (!position) {
    11-
    throw new Error('No tutorial position state found')
    12-
    }
    13-
    if (!tutorial) {
    14-
    throw new Error('Local tutorial not found')
    15-
    }
    16-
    // eslint-disable-next-line
    17-
    const { solution } = tutorial.data.steps[position.stepId].actions
    7+
    const [position, tutorial]: [CR.Position, G.Tutorial | undefined] = await Promise.all([
    8+
    storage.getPosition(),
    9+
    storage.getTutorial(),
    10+
    ])
    11+
    if (!position) {
    12+
    throw new Error('No tutorial position state found')
    13+
    }
    14+
    if (!tutorial || !tutorial.version || !tutorial.version.levels) {
    15+
    throw new Error('Local tutorial not found')
    16+
    }
    17+
    // eslint-disable-next-line
    18+
    19+
    try {
    20+
    const solution = tutorial.version
    21+
    .levels.find((l: G.Level) => l.id === position.levelId)
    22+
    .stages.find((s: G.Stage) => s.id === position.stageId)
    23+
    .steps.find((s: G.Step) => s.id === position.stepId)
    24+
    .solution
    25+
    26+
    await gitClear()
    27+
    await gitLoadCommits(solution, dispatch)
    28+
    } catch (error) {
    29+
    throw new Error(error)
    30+
    }
    1831

    19-
    await gitClear()
    20-
    await gitLoadCommits(solution, dispatch)
    2132
    }

    src/editor/index.ts

    Lines changed: 49 additions & 51 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,69 +1,67 @@
    11
    import * as vscode from 'vscode'
    22
    import * as CR from 'typings'
    3-
    import { createCommands } from './commands'
    3+
    import {createCommands} from './commands'
    44
    import * as storage from '../services/storage'
    55
    import * as git from '../services/git'
    66
    import * as position from '../services/position'
    77

    88
    interface Props {
    9-
    machine: CR.StateMachine
    10-
    setWorkspaceRoot(rootPath: string): void
    9+
    machine: CR.StateMachine
    10+
    setWorkspaceRoot(rootPath: string): void
    1111
    }
    1212

    1313
    class Editor {
    14-
    // extension context set on activation
    15-
    // @ts-ignore
    16-
    private context: vscode.ExtensionContext
    17-
    private machine: CR.StateMachine
    14+
    // extension context set on activation
    15+
    // @ts-ignore
    16+
    private vscodeExt: vscode.ExtensionContext
    17+
    private machine: CR.StateMachine
    1818

    19-
    constructor({ machine, setWorkspaceRoot }: Props) {
    20-
    this.machine = machine
    19+
    constructor({machine, setWorkspaceRoot}: Props) {
    20+
    this.machine = machine
    2121

    22-
    // set workspace root for node executions
    23-
    const { workspace } = vscode
    24-
    const { rootPath } = workspace
    25-
    if (!rootPath) {
    26-
    throw new Error('Requires a workspace. Please open a folder')
    27-
    }
    28-
    setWorkspaceRoot(rootPath)
    29-
    }
    30-
    public activate = (context: vscode.ExtensionContext): void => {
    31-
    console.log('ACTIVATE!')
    32-
    this.context = context
    33-
    // commands
    34-
    this.activateCommands()
    22+
    // set workspace root for node executions
    23+
    const {workspace} = vscode
    24+
    const {rootPath} = workspace
    25+
    if (!rootPath) {
    26+
    throw new Error('Requires a workspace. Please open a folder')
    27+
    }
    28+
    setWorkspaceRoot(rootPath)
    29+
    }
    30+
    public activate = (vscodeExt: vscode.ExtensionContext): void => {
    31+
    console.log('ACTIVATE!')
    32+
    this.vscodeExt = vscodeExt
    33+
    // commands
    34+
    this.activateCommands()
    3535

    36-
    // setup tasks or views here
    37-
    }
    38-
    public deactivate = (): void => {
    39-
    console.log('DEACTIVATE!')
    40-
    // cleanup subscriptions/tasks
    41-
    for (const disposable of this.context.subscriptions) {
    42-
    disposable.dispose()
    43-
    }
    44-
    // shut down state machine
    45-
    console.log('deactivate machine')
    46-
    this.machine.deactivate()
    47-
    }
    36+
    // setup tasks or views here
    37+
    }
    38+
    public deactivate = (): void => {
    39+
    console.log('DEACTIVATE!')
    40+
    // cleanup subscriptions/tasks
    41+
    for (const disposable of this.vscodeExt.subscriptions) {
    42+
    disposable.dispose()
    43+
    }
    44+
    // shut down state machine
    45+
    console.log('deactivate machine')
    46+
    this.machine.deactivate()
    47+
    }
    4848

    49-
    // execute vscode command
    50-
    public dispatch = (type: string, payload?: any) => {
    51-
    vscode.commands.executeCommand(type, payload)
    52-
    }
    49+
    // execute vscode command
    50+
    public dispatch = (type: string, payload?: any) => {
    51+
    vscode.commands.executeCommand(type, payload)
    52+
    }
    5353

    54-
    private activateCommands = (): void => {
    55-
    const commands = createCommands({
    56-
    context: this.context,
    57-
    machine: this.machine,
    58-
    storage,
    59-
    git,
    60-
    position,
    61-
    })
    62-
    for (const cmd in commands) {
    63-
    const command: vscode.Disposable = vscode.commands.registerCommand(cmd, commands[cmd])
    64-
    this.context.subscriptions.push(command)
    65-
    }
    66-
    }
    54+
    private activateCommands = (): void => {
    55+
    const commands = createCommands({
    56+
    vscodeExt: this.vscodeExt,
    57+
    machine: this.machine,
    58+
    git,
    59+
    })
    60+
    for (const cmd in commands) {
    61+
    const command: vscode.Disposable = vscode.commands.registerCommand(cmd, commands[cmd])
    62+
    this.vscodeExt.subscriptions.push(command)
    63+
    }
    64+
    }
    6765
    }
    6866

    6967
    export default Editor

    src/extension.ts

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,10 +1,10 @@
    11
    import * as vscode from 'vscode'
    22
    import {setWorkspaceRoot} from './services/node'
    3-
    import Tutorial from './services/tutorial'
    3+
    import Tutorial, {TutorialModel} from './services/tutorial'
    44
    import StateMachine from './state'
    55
    import Editor from './editor'
    66

    7-
    export const tutorial = new Tutorial()
    7+
    export const tutorial: TutorialModel = new Tutorial()
    88
    // state machine that governs application logic
    99
    export const machine = new StateMachine({dispatch: vscode.commands.executeCommand, tutorial})
    1010

    src/services/storage.ts

    Lines changed: 42 additions & 41 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,77 +1,78 @@
    11
    import * as CR from 'typings'
    2+
    import * as G from 'typings/graphql'
    23
    import * as storage from '../editor/storage'
    34

    45
    // TUTORIAL
    56
    const STORE_TUTORIAL = 'coderoad:tutorial'
    67

    7-
    export async function getTutorial(): Promise<CR.Tutorial | undefined> {
    8-
    return storage.get<CR.Tutorial>(STORE_TUTORIAL)
    8+
    export async function getTutorial(): Promise<G.Tutorial | undefined> {
    9+
    return storage.get<G.Tutorial>(STORE_TUTORIAL)
    910
    }
    1011

    11-
    export async function setTutorial(tutorial: CR.Tutorial): Promise<void> {
    12-
    await storage.update<CR.Tutorial>(STORE_TUTORIAL, tutorial)
    12+
    export async function setTutorial(tutorial: G.Tutorial): Promise<void> {
    13+
    await storage.update<G.Tutorial>(STORE_TUTORIAL, tutorial)
    1314
    }
    1415

    1516
    // POSITION
    1617
    const STORE_POSITION = 'coderoad:position'
    1718

    18-
    const defaultPosition = { levelId: '', stageId: '', stepId: '' }
    19+
    const defaultPosition = {levelId: '', stageId: '', stepId: ''}
    1920

    2021
    export async function getPosition(): Promise<CR.Position> {
    21-
    const position: CR.Position | undefined = storage.get<CR.Position>(STORE_POSITION)
    22-
    return position || defaultPosition
    22+
    const position: CR.Position | undefined = storage.get<CR.Position>(STORE_POSITION)
    23+
    return position || defaultPosition
    2324
    }
    2425

    2526
    export async function setPosition(position: CR.Position): Promise<void> {
    26-
    await storage.update<CR.Position>(STORE_POSITION, position)
    27+
    await storage.update<CR.Position>(STORE_POSITION, position)
    2728
    }
    2829

    2930
    // PROGRESS
    3031
    const STORE_PROGRESS = 'coderoad:progress'
    3132

    32-
    const defaultProgress = { levels: {}, stages: {}, steps: {}, hints: {}, complete: false }
    33+
    const defaultProgress = {levels: {}, stages: {}, steps: {}, hints: {}, complete: false}
    3334

    3435
    export async function getProgress(): Promise<CR.Progress> {
    35-
    const progress: CR.Progress | undefined = await storage.get<CR.Progress>(STORE_PROGRESS)
    36-
    return progress || defaultProgress
    36+
    const progress: CR.Progress | undefined = await storage.get<CR.Progress>(STORE_PROGRESS)
    37+
    return progress || defaultProgress
    3738
    }
    3839

    3940
    export async function resetProgress(): Promise<void> {
    40-
    await storage.update<CR.Progress>(STORE_PROGRESS, defaultProgress)
    41+
    await storage.update<CR.Progress>(STORE_PROGRESS, defaultProgress)
    4142
    }
    4243

    4344
    interface ProgressUpdate {
    44-
    levels?: {
    45-
    [levelId: string]: boolean
    46-
    }
    47-
    stages?: {
    48-
    [stageid: string]: boolean
    49-
    }
    50-
    steps?: {
    51-
    [stepId: string]: boolean
    52-
    }
    45+
    levels?: {
    46+
    [levelId: string]: boolean
    47+
    }
    48+
    stages?: {
    49+
    [stageid: string]: boolean
    50+
    }
    51+
    steps?: {
    52+
    [stepId: string]: boolean
    53+
    }
    5354
    }
    5455

    5556
    export async function setProgress(record: ProgressUpdate): Promise<void> {
    56-
    const progress = await getProgress()
    57-
    if (record.levels) {
    58-
    progress.levels = {
    59-
    ...progress.levels,
    60-
    ...record.levels,
    61-
    }
    62-
    }
    63-
    if (record.stages) {
    64-
    progress.stages = {
    65-
    ...progress.stages,
    66-
    ...record.stages,
    67-
    }
    68-
    }
    69-
    if (record.steps) {
    70-
    progress.steps = {
    71-
    ...progress.steps,
    72-
    ...record.steps,
    73-
    }
    74-
    }
    57+
    const progress = await getProgress()
    58+
    if (record.levels) {
    59+
    progress.levels = {
    60+
    ...progress.levels,
    61+
    ...record.levels,
    62+
    }
    63+
    }
    64+
    if (record.stages) {
    65+
    progress.stages = {
    66+
    ...progress.stages,
    67+
    ...record.stages,
    68+
    }
    69+
    }
    70+
    if (record.steps) {
    71+
    progress.steps = {
    72+
    ...progress.steps,
    73+
    ...record.steps,
    74+
    }
    75+
    }
    7576

    76-
    await storage.update<CR.Progress>(STORE_PROGRESS, progress)
    77+
    await storage.update<CR.Progress>(STORE_PROGRESS, progress)
    7778
    }

    0 commit comments

    Comments
     (0)
    0