Skip to content

Feature/load from GitHub #174

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 17 commits into from
Apr 2, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
typings update first pass
  • Loading branch information
ShMcK committed Mar 31, 2020
commit 8342bb2bcc560289299025b456fcd327e7d5d319
16 changes: 8 additions & 8 deletions src/channel/state/Progress.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import * as CR from 'typings'
import * as T from 'typings'
import * as TT from 'typings/tutorial'
import * as vscode from 'vscode'
import Storage from '../../services/storage'

const defaultValue: CR.Progress = {
const defaultValue: T.Progress = {
levels: {},
steps: {},
complete: false,
}

// hold current progress and sync to storage based on tutorial.id/version
class Progress {
private value: CR.Progress
private storage: Storage<CR.Progress> | undefined
private value: T.Progress
private storage: Storage<T.Progress> | undefined
constructor() {
this.value = defaultValue
}
public setTutorial = async (workspaceState: vscode.Memento, tutorial: G.Tutorial): Promise<CR.Progress> => {
this.storage = new Storage<CR.Progress>({
public setTutorial = async (workspaceState: vscode.Memento, tutorial: TT.Tutorial): Promise<T.Progress> => {
this.storage = new Storage<T.Progress>({
key: `coderoad:progress:${tutorial.id}:${tutorial.version}`,
storage: workspaceState,
defaultValue,
@@ -28,7 +28,7 @@ class Progress {
public get = () => {
return this.value
}
public set = (value: CR.Progress) => {
public set = (value: T.Progress) => {
this.value = value
if (!this.storage) {
return defaultValue
@@ -39,7 +39,7 @@ class Progress {
public reset = () => {
this.set(defaultValue)
}
public setStepComplete = (tutorialData: TT.TutorialData, stepId: string): CR.Progress => {
public setStepComplete = (tutorialData: TT.TutorialData, stepId: string): T.Progress => {
const next = this.value
// mark step complete
next.steps[stepId] = true
2 changes: 1 addition & 1 deletion typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -69,7 +69,7 @@ export interface MachineStateSchema {
Setup: {
states: {
Startup: {}
Authenticate: {}
// Authenticate: {}
Error: {}
LoadStoredTutorial: {}
Start: {}
1 change: 1 addition & 0 deletions typings/tutorial.d.ts
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ export type Step = {
/** A tutorial for use in VSCode CodeRoad */
export type Tutorial = {
id: string
version: string
summary: TutorialSummary
data: TutorialData
}
6 changes: 1 addition & 5 deletions web-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { ApolloProvider } from '@apollo/react-hooks'
import * as React from 'react'
import ErrorBoundary from './components/ErrorBoundary'
import Routes from './Routes'
import client from './services/apollo'

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

21 changes: 1 addition & 20 deletions web-app/src/components/Error/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ApolloError } from 'apollo-boost'
import { GraphQLError } from 'graphql'
import * as React from 'react'
import { css, jsx } from '@emotion/core'
import onError from '../../services/sentry/onError'
@@ -34,25 +33,7 @@ const ErrorView = ({ error }: Props) => {
return (
<div css={styles.container}>
<h1>Error</h1>
{error.graphQLErrors && (
<div>
{error.graphQLErrors.map(({ message, locations, path }: GraphQLError, index: number) => (
<h5 key={index}>
<b>[GraphQL error]:</b> Message: {message}, Location: {locations}, Path: {path}
</h5>
))}
</div>
)}
{error.networkError && (
<h5>
<b>[Network error]:</b> {error.networkError.message}
</h5>
)}
{error.extraInfo && (
<p>
<b>[Extra info]:</b> {JSON.stringify(error.extraInfo)}
</p>
)}
<div>{JSON.stringify(error)}</div>
</div>
)
}
12 changes: 5 additions & 7 deletions web-app/src/containers/Overview/OverviewPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import moment from 'moment'
import Button from '../../components/Button'
import Markdown from '../../components/Markdown'
@@ -71,9 +71,7 @@ const styles = {
interface Props {
title: string
description: string
createdBy: G.User
updatedAt: string
levels: G.Level[]
levels: TT.Level[]
onNext(): void
onBack(): void
}
@@ -93,15 +91,15 @@ const Summary = (props: Props) => (
</div>
<h1 css={styles.title}>{props.title}</h1>
<h3>{props.description}</h3>
<h5 css={styles.meta}>
{/* <h5 css={styles.meta}>
<div css={{ marginRight: '2rem' }}>Created by {props.createdBy.name}</div>
<div>Last updated {moment(props.updatedAt).format('M/YYYY')}</div>
</h5>
</h5> */}
</div>
<div>
<div css={styles.levelList}>
<h2>Content</h2>
{props.levels.map((level: G.Level, index: number) => (
{props.levels.map((level: TT.Level, index: number) => (
<div key={index}>
<h3>
{index + 1}. {level.title}
78 changes: 31 additions & 47 deletions web-app/src/containers/Overview/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useQuery } from '@apollo/react-hooks'
import * as React from 'react'
import * as CR from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import ErrorView from '../../components/Error'
import queryTutorial from '../../services/apollo/queries/tutorial'
import OverviewPage from './OverviewPage'
import LoadingPage from '../Loading'

@@ -13,7 +12,7 @@ interface PageProps {
}

interface TutorialData {
tutorial: G.Tutorial
tutorial: TT.Tutorial
}

interface TutorialDataVariables {
@@ -27,51 +26,36 @@ const Overview = (props: PageProps) => {
if (!tutorial) {
throw new Error('Tutorial not found in summary page')
}
const { loading, error, data } = useQuery<TutorialData, TutorialDataVariables>(queryTutorial, {
fetchPolicy: 'no-cache', // to ensure latest
variables: {
tutorialId: tutorial.id,
// version: tutorial.version.version, // TODO: re-enable latest
},
})

if (loading) {
return <LoadingPage text="Loading Summary..." context={props.context} />
}

if (error) {
return <ErrorView error={error} />
}

if (!data) {
return null
}

const onNext = () =>
props.send({
type: 'TUTORIAL_START',
payload: {
tutorial: data.tutorial,
},
})

const onBack = () => props.send({ type: 'BACK' })

const { title, description } = data.tutorial.summary
const { createdBy, updatedAt, data: tutorialData } = data.tutorial.version
const { levels } = tutorialData

return (
<OverviewPage
title={title}
description={description}
createdBy={createdBy}
updatedAt={updatedAt}
levels={levels}
onNext={onNext}
onBack={onBack}
/>
)
console.log('todo overview load')

return <div>Overview Page</div>

// const onNext = () =>
// props.send({
// type: 'TUTORIAL_START',
// payload: {
// tutorial: data.tutorial,
// },
// })

// const onBack = () => props.send({ type: 'BACK' })

// const { title, description } = data.tutorial.summary
// const { createdBy, updatedAt, data: tutorialData } = data.tutorial.version
// const { levels } = tutorialData

// return (
// <OverviewPage
// title={title}
// description={description}
// createdBy={createdBy}
// updatedAt={updatedAt}
// levels={levels}
// onNext={onNext}
// onBack={onBack}
// />
// )
}

export default Overview
9 changes: 4 additions & 5 deletions web-app/src/containers/SelectTutorial/SelectTutorial.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import * as T from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import { css, jsx } from '@emotion/core'
import TutorialItem from './TutorialItem'

@@ -18,11 +18,11 @@ const styles = {

interface Props {
send(action: T.Action): void
tutorialList: G.Tutorial[]
tutorialList: TT.Tutorial[]
}

const SelectTutorial = (props: Props) => {
const onSelect = (tutorial: G.Tutorial) => {
const onSelect = (tutorial: TT.Tutorial) => {
props.send({
type: 'SELECT_TUTORIAL',
payload: {
@@ -36,13 +36,12 @@ const SelectTutorial = (props: Props) => {
<span>Select a tutorial to launch in this workspace:</span>
</div>
<div>
{props.tutorialList.map((tutorial: G.Tutorial) => (
{props.tutorialList.map((tutorial: TT.Tutorial) => (
<TutorialItem
key={tutorial.id}
onSelect={() => onSelect(tutorial)}
title={tutorial.summary.title || ''}
description={tutorial.summary.description || ''}
createdBy={tutorial.createdBy}
/>
))}
</div>
16 changes: 2 additions & 14 deletions web-app/src/containers/SelectTutorial/TutorialItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import { css, jsx } from '@emotion/core'
import Card from '../../components/Card'
import Tag from '../../components/Tag'
@@ -49,21 +49,9 @@ const styles = {
interface Props {
title: string
description: string
createdBy?: G.User | null
onSelect(): void
}

// icons from https://konpa.github.io/devicon/
const LanguageIcon = () => (
<svg viewBox="0 0 128 128" css={styles.languageIcon}>
<path fill="#F0DB4F" d="M1.408 1.408h125.184v125.185h-125.184z"></path>
<path
fill="#323330"
d="M116.347 96.736c-.917-5.711-4.641-10.508-15.672-14.981-3.832-1.761-8.104-3.022-9.377-5.926-.452-1.69-.512-2.642-.226-3.665.821-3.32 4.784-4.355 7.925-3.403 2.023.678 3.938 2.237 5.093 4.724 5.402-3.498 5.391-3.475 9.163-5.879-1.381-2.141-2.118-3.129-3.022-4.045-3.249-3.629-7.676-5.498-14.756-5.355l-3.688.477c-3.534.893-6.902 2.748-8.877 5.235-5.926 6.724-4.236 18.492 2.975 23.335 7.104 5.332 17.54 6.545 18.873 11.531 1.297 6.104-4.486 8.08-10.234 7.378-4.236-.881-6.592-3.034-9.139-6.949-4.688 2.713-4.688 2.713-9.508 5.485 1.143 2.499 2.344 3.63 4.26 5.795 9.068 9.198 31.76 8.746 35.83-5.176.165-.478 1.261-3.666.38-8.581zm-46.885-37.793h-11.709l-.048 30.272c0 6.438.333 12.34-.714 14.149-1.713 3.558-6.152 3.117-8.175 2.427-2.059-1.012-3.106-2.451-4.319-4.485-.333-.584-.583-1.036-.667-1.071l-9.52 5.83c1.583 3.249 3.915 6.069 6.902 7.901 4.462 2.678 10.459 3.499 16.731 2.059 4.082-1.189 7.604-3.652 9.448-7.401 2.666-4.915 2.094-10.864 2.07-17.444.06-10.735.001-21.468.001-32.237z"
></path>
</svg>
)

const TutorialItem = (props: Props) => (
<Card onClick={props.onSelect}>
<div style={styles.card}>
@@ -72,7 +60,7 @@ const TutorialItem = (props: Props) => (
</div>
<div css={styles.right}>
<h2 css={styles.title}>{props.title}</h2>
{props.createdBy && <h3 css={styles.author}>{props.createdBy.name}</h3>}
{/* {props.createdBy && <h3 css={styles.author}>{props.createdBy.name}</h3>} */}
<div css={styles.tags}>
<Tag>javascript</Tag>
</div>
23 changes: 3 additions & 20 deletions web-app/src/containers/SelectTutorial/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useQuery } from '@apollo/react-hooks'
import * as React from 'react'
import * as T from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import ErrorView from '../../components/Error'
import queryTutorials from '../../services/apollo/queries/tutorials'
import LoadingPage from '../Loading'
import SelectTutorial from './SelectTutorial'

@@ -13,27 +12,11 @@ interface ContainerProps {
}

interface TutorialsData {
tutorials: G.Tutorial[]
tutorials: TT.Tutorial[]
}

const SelectPageContainer = (props: ContainerProps) => {
const { data, loading, error } = useQuery<TutorialsData>(queryTutorials, {
fetchPolicy: 'no-cache',
})

if (error) {
return <ErrorView error={error} />
}

if (loading) {
return <LoadingPage text="Loading tutorials" context={props.context} />
}

if (!data) {
return null
}

return <SelectTutorial tutorialList={data.tutorials} send={props.send} />
return <div>SelectTutorial</div>
}

export default SelectPageContainer
4 changes: 2 additions & 2 deletions web-app/src/containers/Start/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import * as CR from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import BetaBadge from '../../components/BetaBadge'
import { css, jsx } from '@emotion/core'
import Button from '../../components/Button'
@@ -46,7 +46,7 @@ const styles = {
interface Props {
onContinue(): void
onNew(): void
tutorial?: G.Tutorial
tutorial?: TT.Tutorial
}

export const StartPage = (props: Props) => (
6 changes: 3 additions & 3 deletions web-app/src/containers/Tutorial/CompletedPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import * as CR from 'typings'
import * as T from 'typings'
import { css, jsx } from '@emotion/core'
import Button from '../../components/Button'

@@ -17,8 +17,8 @@ const styles = {
}

interface Props {
context: CR.MachineContext
send(action: CR.Action | string): void
context: T.MachineContext
send(action: T.Action | string): void
}

const CompletedPage = (props: Props) => {
6 changes: 3 additions & 3 deletions web-app/src/containers/Tutorial/LevelPage/Level.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import * as T from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import { css, jsx } from '@emotion/core'
import Button from '../../../components/Button'
import Markdown from '../../../components/Markdown'
@@ -77,7 +77,7 @@ const styles = {
}

interface Props {
level: G.Level & { status: T.ProgressStatus; index: number; steps: Array<G.Step & { status: T.ProgressStatus }> }
level: TT.Level & { status: T.ProgressStatus; index: number; steps: Array<TT.Step & { status: T.ProgressStatus }> }
processes: T.ProcessEvent[]
testStatus: T.TestStatus | null
onContinue(): void
@@ -114,7 +114,7 @@ const Level = ({ level, onContinue, onLoadSolution, processes, testStatus }: Pro
<div css={styles.tasks}>
<div css={styles.header}>Tasks</div>
<div css={styles.steps}>
{level.steps.map((step: (G.Step & { status: T.ProgressStatus }) | null, index: number) => {
{level.steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, index: number) => {
if (!step) {
return null
}
1 change: 0 additions & 1 deletion web-app/src/containers/Tutorial/LevelPage/Step.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ import * as T from 'typings'
import { css, jsx } from '@emotion/core'
import Checkbox from '../../../components/Checkbox'
import Markdown from '../../../components/Markdown'
import StepHelp from '../../../components/StepHelp'

interface Props {
order: number
14 changes: 7 additions & 7 deletions web-app/src/containers/Tutorial/LevelPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import * as T from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import * as selectors from '../../../services/selectors'
import Level from './Level'

@@ -12,8 +12,8 @@ interface PageProps {
const LevelSummaryPageContainer = (props: PageProps) => {
const { position, progress, processes, testStatus, error } = props.context

const version = selectors.currentVersion(props.context)
const levelData: G.Level = selectors.currentLevel(props.context)
const tutorial = selectors.currentTutorial(props.context)
const levelData: TT.Level = selectors.currentLevel(props.context)

const onContinue = (): void => {
props.send({
@@ -28,15 +28,15 @@ const LevelSummaryPageContainer = (props: PageProps) => {
props.send({ type: 'STEP_SOLUTION_LOAD' })
}

const level: G.Level & {
const level: TT.Level & {
status: T.ProgressStatus
index: number
steps: Array<G.Step & { status: T.ProgressStatus }>
steps: Array<TT.Step & { status: T.ProgressStatus }>
} = {
...levelData,
index: version.data.levels.findIndex((l: G.Level) => l.id === position.levelId),
index: tutorial.data.levels.findIndex((l: TT.Level) => l.id === position.levelId),
status: progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE',
steps: levelData.steps.map((step: G.Step) => {
steps: levelData.steps.map((step: TT.Step) => {
// label step status for step component
let status: T.ProgressStatus = 'INCOMPLETE'
if (progress.steps[step.id]) {
18 changes: 0 additions & 18 deletions web-app/src/services/apollo/auth.ts

This file was deleted.

10 changes: 0 additions & 10 deletions web-app/src/services/apollo/index.ts

This file was deleted.

14 changes: 0 additions & 14 deletions web-app/src/services/apollo/mutations/authenticate.ts

This file was deleted.

44 changes: 0 additions & 44 deletions web-app/src/services/apollo/queries/summary.ts

This file was deleted.

53 changes: 0 additions & 53 deletions web-app/src/services/apollo/queries/tutorial.ts

This file was deleted.

27 changes: 0 additions & 27 deletions web-app/src/services/apollo/queries/tutorials.ts

This file was deleted.

17 changes: 9 additions & 8 deletions web-app/src/services/selectors/position.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { createSelector } from 'reselect'
import * as CR from 'typings'
import * as G from 'typings/graphql'
import * as tutorial from './tutorial'
import * as T from 'typings'
import * as TT from 'typings/tutorial'

export const defaultPosition = () => ({
levelId: '',
stepId: null,
})

export const initialPosition = createSelector(tutorial.currentVersion, (version: G.TutorialVersion) => {
const level = version.data.levels[0]
const position: CR.Position = {
export const initialPosition = (context: T.MachineContext) => {
if (!context.tutorial) {
throw new Error('Tutorial not found at initialPosition check')
}
const level: TT.Level = context.tutorial.data.levels[0]
const position: T.Position = {
levelId: level.id,
stepId: level.steps.length ? level.steps[0].id : null,
}
return position
})
}
35 changes: 13 additions & 22 deletions web-app/src/services/selectors/tutorial.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createSelector } from 'reselect'
import { MachineContext } from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import onError from '../../services/sentry/onError'

export const currentTutorial = ({ tutorial }: MachineContext): G.Tutorial => {
export const currentTutorial = ({ tutorial }: MachineContext): TT.Tutorial => {
if (!tutorial) {
const error = new Error('Tutorial not found')
onError(error)
@@ -12,38 +12,29 @@ export const currentTutorial = ({ tutorial }: MachineContext): G.Tutorial => {
return tutorial
}

export const currentVersion = createSelector(currentTutorial, (tutorial: G.Tutorial) => {
if (!tutorial.version) {
const error = new Error('Tutorial version not found')
onError(error)
throw error
}
return tutorial.version
})

export const currentLevel = (context: MachineContext): G.Level =>
export const currentLevel = (context: MachineContext): TT.Level =>
createSelector(
currentVersion,
(version: G.TutorialVersion): G.Level => {
currentTutorial,
(tutorial: TT.Tutorial): TT.Level => {
// merge in the updated position
// sent with the test to ensure consistency
const levels: G.Level[] = version.data.levels
const levels: TT.Level[] = tutorial.data.levels

const levelIndex = levels.findIndex((l: G.Level) => l.id === context.position.levelId)
const levelIndex = levels.findIndex((l: TT.Level) => l.id === context.position.levelId)
if (levelIndex < 0) {
const error = new Error(`Level not found when selecting level for ${version}`)
const error = new Error(`Level not found when selecting level for ${tutorial.id}`)
onError(error)
throw error
}
const level: G.Level = levels[levelIndex]
const level: TT.Level = levels[levelIndex]

return level
},
)(context)

export const currentStep = (context: MachineContext): G.Step | null =>
createSelector(currentLevel, (level: G.Level): G.Step | null => {
const steps: G.Step[] = level.steps
const step: G.Step | null = steps.find((s: G.Step) => s.id === context.position.stepId) || null
export const currentStep = (context: MachineContext): TT.Step | null =>
createSelector(currentLevel, (level: TT.Level): TT.Step | null => {
const steps: TT.Step[] = level.steps
const step: TT.Step | null = steps.find((s: TT.Step) => s.id === context.position.stepId) || null
return step
})(context)
28 changes: 14 additions & 14 deletions web-app/src/services/state/actions/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as T from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import { assign, send, ActionFunctionMap } from 'xstate'
import * as selectors from '../../selectors'
import onError from '../../../services/sentry/onError'
@@ -50,17 +50,17 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
const { position } = context
// merge in the updated position
// sent with the test to ensure consistency
const level: G.Level = selectors.currentLevel(context)
const steps: G.Step[] = level.steps
const level: TT.Level = selectors.currentLevel(context)
const steps: TT.Step[] = level.steps

// final step but not completed
if (steps[steps.length - 1].id === position.stepId) {
return position
}

const stepIndex = steps.findIndex((s: G.Step) => s.id === position.stepId)
const stepIndex = steps.findIndex((s: TT.Step) => s.id === position.stepId)

const step: G.Step = steps[stepIndex + 1]
const step: TT.Step = steps[stepIndex + 1]

const nextPosition: T.Position = {
...position,
@@ -74,13 +74,13 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
updateLevelPosition: assign({
position: (context: T.MachineContext): any => {
const { position } = context
const version = selectors.currentVersion(context)
const tutorial = selectors.currentTutorial(context)
// merge in the updated position
// sent with the test to ensure consistency
const levels: G.Level[] = version.data.levels
const levels: TT.Level[] = tutorial.data.levels

const levelIndex = levels.findIndex((l: G.Level) => l.id === position.levelId)
const level: G.Level = levels[levelIndex + 1]
const levelIndex = levels.findIndex((l: TT.Level) => l.id === position.levelId)
const level: TT.Level = levels[levelIndex + 1]

const nextPosition: T.Position = {
levelId: level.id,
@@ -129,10 +129,10 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {

const level = selectors.currentLevel(context)

const steps: G.Step[] = level.steps
const steps: TT.Step[] = level.steps

if (steps.length && position.stepId) {
const stepIndex = steps.findIndex((s: G.Step) => s.id === position.stepId)
const stepIndex = steps.findIndex((s: TT.Step) => s.id === position.stepId)
const stepComplete = progress.steps[position.stepId]
const finalStep = stepIndex > -1 && stepIndex === steps.length - 1
const hasNextStep = !finalStep && !stepComplete
@@ -153,7 +153,7 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {

// @ts-ignore
const levels = context.tutorial.version.data.levels || []
const levelIndex = levels.findIndex((l: G.Level) => l.id === position.levelId)
const levelIndex = levels.findIndex((l: TT.Level) => l.id === position.levelId)
const finalLevel = levelIndex > -1 && levelIndex === levels.length - 1
const hasNextLevel = !finalLevel

@@ -175,12 +175,12 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
(context: T.MachineContext): T.Action => {
const { position, progress } = context

const level: G.Level = selectors.currentLevel(context)
const level: TT.Level = selectors.currentLevel(context)

const { steps } = level

if (steps.length && position.stepId) {
const stepIndex = steps.findIndex((s: G.Step) => s.id === position.stepId)
const stepIndex = steps.findIndex((s: TT.Step) => s.id === position.stepId)
const finalStep = stepIndex === steps.length - 1
const stepComplete = progress.steps[position.stepId]
// not final step, or final step but not complete
8 changes: 4 additions & 4 deletions web-app/src/services/state/actions/editor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as CR from 'typings'
import * as G from 'typings/graphql'
import * as TT from 'typings/tutorial'
import * as selectors from '../../selectors'

export default (editorSend: any) => ({
@@ -34,7 +34,7 @@ export default (editorSend: any) => ({
})
},
loadLevel(context: CR.MachineContext): void {
const level: G.Level = selectors.currentLevel(context)
const level: TT.Level = selectors.currentLevel(context)
if (level.setup) {
// load step actions
editorSend({
@@ -44,7 +44,7 @@ export default (editorSend: any) => ({
}
},
loadStep(context: CR.MachineContext): void {
const step: G.Step | null = selectors.currentStep(context)
const step: TT.Step | null = selectors.currentStep(context)
if (step && step.setup) {
// load step actions
editorSend({
@@ -57,7 +57,7 @@ export default (editorSend: any) => ({
}
},
editorLoadSolution(context: CR.MachineContext): void {
const step: G.Step | null = selectors.currentStep(context)
const step: TT.Step | null = selectors.currentStep(context)
// tell editor to load solution commit
if (step && step.solution) {
editorSend({
26 changes: 13 additions & 13 deletions web-app/src/services/state/machine.ts
Original file line number Diff line number Diff line change
@@ -38,23 +38,23 @@ export const createMachine = (options: any) => {
onEntry: ['loadEnv'],
on: {
ENV_LOAD: {
target: 'Authenticate',
target: 'LoadStoredTutorial',
actions: ['setEnv'],
},
},
},
Authenticate: {
invoke: {
src: services.authenticate,
onDone: 'LoadStoredTutorial',
onError: {
target: 'Error',
actions: assign({
error: (context, event) => event.data,
}),
},
},
},
// Authenticate: {
// invoke: {
// src: services.authenticate,
// onDone: 'LoadStoredTutorial',
// onError: {
// target: 'Error',
// actions: assign({
// error: (context, event) => event.data,
// }),
// },
// },
// },
Error: {},
LoadStoredTutorial: {
onEntry: ['loadStoredTutorial'],
64 changes: 0 additions & 64 deletions web-app/src/services/state/services/authenticate.ts

This file was deleted.

1 change: 0 additions & 1 deletion web-app/src/services/state/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { authenticate } from './authenticate'
export { loadTutorialData } from './loadTutorialData'
export { loadTutorialSummary } from './loadTutorialSummary'
33 changes: 16 additions & 17 deletions web-app/src/services/state/services/loadTutorialData.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import * as CR from 'typings'
import * as G from 'typings/graphql'
import client from '../../apollo'
import tutorialQuery from '../../apollo/queries/tutorial'
import * as TT from 'typings/tutorial'
import onError from '../../../services/sentry/onError'

interface TutorialData {
tutorial: G.Tutorial
tutorial: TT.Tutorial
}

interface TutorialDataVariables {
@@ -22,19 +20,20 @@ export async function loadTutorialData(context: CR.MachineContext): Promise<any>
}

try {
const result = await client.query<TutorialData, TutorialDataVariables>({
query: tutorialQuery,
variables: {
tutorialId: context.tutorial.id,
// version: context.tutorial.version.version, // TODO: reimplement version
},
})
if (!result || !result.data || !result.data.tutorial) {
const message = 'No tutorial returned from tutorial config query'
onError(new Error(message))
return Promise.reject(message)
}
return Promise.resolve(result.data.tutorial)
console.log('todo load tutorial')
// const result = await client.query<TutorialData, TutorialDataVariables>({
// query: tutorialQuery,
// variables: {
// tutorialId: context.tutorial.id,
// // version: context.tutorial.version.version, // TODO: reimplement version
// },
// })
// if (!result || !result.data || !result.data.tutorial) {
// const message = 'No tutorial returned from tutorial config query'
// onError(new Error(message))
// return Promise.reject(message)
// }
// return Promise.resolve(result.data.tutorial)
} catch (error) {
const message: CR.ErrorMessage = { title: 'Failed to load tutorial config', description: error.message }
onError(error)
33 changes: 16 additions & 17 deletions web-app/src/services/state/services/loadTutorialSummary.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import * as CR from 'typings'
import * as G from 'typings/graphql'
import client from '../../apollo'
import summaryQuery from '../../apollo/queries/summary'
import * as TT from 'typings/tutorial'
import onError from '../../../services/sentry/onError'

interface TutorialData {
tutorial: G.Tutorial
tutorial: TT.Tutorial
}

interface TutorialDataVariables {
@@ -22,19 +20,20 @@ export async function loadTutorialSummary(context: CR.MachineContext): Promise<a
}

try {
const result = await client.query<TutorialData, TutorialDataVariables>({
query: summaryQuery,
variables: {
tutorialId: context.tutorial.id,
// version: context.tutorial.version.version, // TODO: reimplement version
},
})
if (!result || !result.data || !result.data.tutorial) {
const message = 'No tutorial returned from tutorial config query'
onError(new Error(message))
return Promise.reject(message)
}
return Promise.resolve(result.data.tutorial)
console.log('load tutorial summary')
// const result = await client.query<TutorialData, TutorialDataVariables>({
// query: summaryQuery,
// variables: {
// tutorialId: context.tutorial.id,
// // version: context.tutorial.version.version, // TODO: reimplement version
// },
// })
// if (!result || !result.data || !result.data.tutorial) {
// const message = 'No tutorial returned from tutorial config query'
// onError(new Error(message))
// return Promise.reject(message)
// }
// return Promise.resolve(result.data.tutorial)
} catch (error) {
const message: CR.ErrorMessage = { title: 'Failed to load tutorial config', description: error.message }
onError(error)
6 changes: 3 additions & 3 deletions web-app/stories/Level.stories.tsx
Original file line number Diff line number Diff line change
@@ -3,14 +3,14 @@ import { withKnobs } from '@storybook/addon-knobs'
import { storiesOf } from '@storybook/react'
import React from 'react'
import * as T from '../../typings'
import * as G from '../../typings/graphql'
import * as TT from '../../typings/tutorial'
import Level from '../src/containers/Tutorial/LevelPage/Level'
import SideBarDecorator from './utils/SideBarDecorator'

type ModifiedLevel = G.Level & {
type ModifiedLevel = TT.Level & {
status: T.ProgressStatus
index: number
steps: Array<G.Step & { status: T.ProgressStatus }>
steps: Array<TT.Step & { status: T.ProgressStatus }>
}

storiesOf('Level', module)
94 changes: 0 additions & 94 deletions web-app/stories/data/basic.ts

This file was deleted.