Skip to content

Feature/solution actions #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 29, 2019
18 changes: 6 additions & 12 deletions src/actions/solutionActions.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
// import * as CR from 'typings'
import * as G from 'typings/graphql'
// import {TutorialModel} from '../services/tutorial'
// import {gitLoadCommits, gitClear} from '../services/git'

const solutionActions = async (stepActions: G.StepActions): Promise<void> => {
// TODO: should load same as commits

// const step: G.Step = tutorialModel.step()
// const solution = step.solution

// await gitClear()
// await gitLoadCommits(solution, dispatch)
import * as vscode from 'vscode'
import * as git from '../services/git'
import setupActions from './setupActions'

const solutionActions = async (workspaceRoot: vscode.WorkspaceFolder, stepActions: G.StepActions): Promise<void> => {
await git.clear()
return setupActions(workspaceRoot, stepActions)
}

export default solutionActions
4 changes: 3 additions & 1 deletion src/channel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ class Channel implements Channel {
return
// load solution step actions (git commits, commands, open files)
case 'SOLUTION_ACTIONS':
solutionActions(action.payload)
await solutionActions(this.workspaceRoot, action.payload)
// run test following solution to update position
vscode.commands.executeCommand('coderoad.run_test', action.payload)
return

default:
Expand Down
2 changes: 1 addition & 1 deletion src/channel/state/Progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Progress {
public set = (value: CR.Progress) => {
this.value = value
if (!this.storage) {
throw new Error('Tutorial storage not found')
return defaultValue
}
this.storage.set(value)
return this.value
Expand Down
6 changes: 3 additions & 3 deletions typings/graphql.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export type Stage = {
step?: Maybe<Step>,
steps: Array<Step>,
setup?: Maybe<StepActions>,
status: string
status: 'ACTIVE' | 'COMPLETE' | 'INCOMPLETE'
};


Expand All @@ -151,8 +151,8 @@ export type Step = {
text: Scalars['String'],
setup: StepActions,
solution: StepActions,
status: string
};
status: 'ACTIVE' | 'COMPLETE' | 'INCOMPLETE'
}

export type StepActions = {
__typename?: 'StepActions',
Expand Down
9 changes: 6 additions & 3 deletions web-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import * as React from 'react'
import { ApolloProvider } from '@apollo/react-hooks'

import ErrorBoundary from './components/ErrorBoundary'
import client from './services/apollo'
import Routes from './Routes'

const App = () => (
<ApolloProvider client={client}>
<Routes />
</ApolloProvider>
<ErrorBoundary>
<ApolloProvider client={client}>
<Routes />
</ApolloProvider>
</ErrorBoundary>
)

export default App
23 changes: 23 additions & 0 deletions web-app/src/components/ErrorBoundary/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react'

class ErrorBoundary extends React.Component {
public state = { hasError: false }

public componentDidCatch(error: Error, info: any) {
// Display fallback UI
this.setState({ hasError: true })
// You can also log the error to an error reporting service
console.error(error)
console.log(info)
}

public render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>
}
return this.props.children
}
}

export default ErrorBoundary
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react'
import Markdown from '../../../../../components/Markdown'
import { Button } from '@alifd/next'

const styles = {
// active: {
Expand All @@ -12,16 +13,29 @@ const styles = {

interface Props {
text?: string | null
hide: boolean
mode: 'INCOMPLETE' | 'ACTIVE' | 'COMPLETE'
onLoadSolution(): void
}

const StepDescription = ({ text, hide }: Props) => {
if (hide) {
const StepDescription = ({ text, mode, onLoadSolution }: Props) => {
const [loadedSolution, setLoadedSolution] = React.useState()

const onClickHandler = () => {
if (!loadedSolution) {
setLoadedSolution(true)
onLoadSolution()
}
}

if (mode === 'INCOMPLETE') {
return null
}

const showLoadSolution = mode === 'ACTIVE' && !loadedSolution
return (
<div style={styles.card}>
<Markdown>{text || ''}</Markdown>
{showLoadSolution && <Button onClick={onClickHandler}>Load Solution</Button>}
</div>
)
}
Expand Down
14 changes: 7 additions & 7 deletions web-app/src/containers/Tutorial/StagePage/Stage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ const styles = {

interface Props {
stage: T.Stage
onContinue(): void
onSave(): void
onContinue(): void
onSave(): void
onLoadSolution(): void
}

const Stage = ({ stage, onContinue, onSave }: Props) => {
const Stage = ({ stage, onContinue, onSave, onLoadSolution }: Props) => {
if (!stage.steps) {
throw new Error('No Stage steps found')
}
Expand All @@ -50,12 +51,11 @@ const Stage = ({ stage, onContinue, onSave }: Props) => {
if (!step) {
return null
}
const hide = step.status === 'INCOMPLETE'
return (
<Step.Item
key={step.id}
title={step.title || `Step ${index + 1}`}
content={<StepDescription text={step.text} hide={hide} />}
content={<StepDescription text={step.text} mode={step.status} onLoadSolution={onLoadSolution} />}
/>
)
})}
Expand All @@ -67,10 +67,10 @@ const Stage = ({ stage, onContinue, onSave }: Props) => {
<Button onClick={onContinue}>Continue</Button>
</div>
) : (
<div style={styles.options}>
<div style={styles.options}>
<Button onClick={onSave}>Save</Button>
</div>
)}
)}
</div>
)
}
Expand Down
6 changes: 5 additions & 1 deletion web-app/src/containers/Tutorial/StagePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ const StageSummaryPageContainer = (props: PageProps) => {
})
}

const onLoadSolution = (): void => {
props.send({ type: 'STEP_SOLUTION_LOAD' })
}

stage.steps.forEach((step: G.Step) => {
if (progress.steps[step.id]) {
step.status = 'COMPLETE'
Expand All @@ -44,7 +48,7 @@ const StageSummaryPageContainer = (props: PageProps) => {
})
stage.status = progress.stages[position.stageId] ? 'COMPLETE' : 'ACTIVE'

return <Stage stage={stage} onContinue={onContinue} onSave={onSave} />
return <Stage stage={stage} onContinue={onContinue} onSave={onSave} onLoadSolution={onLoadSolution} />
}

export default StageSummaryPageContainer
11 changes: 11 additions & 0 deletions web-app/src/services/state/actions/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@ export default {
})
}
},
editorLoadSolution(context: CR.MachineContext): void {
const step: G.Step = selectors.currentStep(context)
// tell editor to load solution commit
channel.editorSend({
type: 'SOLUTION_ACTIONS',
payload: {
stepId: step.id,
...step.solution,
}
})
},
clearStorage(): void {
channel.editorSend({type: 'TUTORIAL_CLEAR'})
}
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/services/state/machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export const machine = Machine<CR.MachineContext, CR.MachineStateSchema, CR.Mach
on: {
TEST_RUN: 'TestRunning',
STEP_SOLUTION_LOAD: {
actions: ['callSolution'],
actions: ['editorLoadSolution'],
},
},
},
Expand Down