Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix/continue#301

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ShMcK merged 5 commits intomasterfromfix/continue
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
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
6 changes: 4 additions & 2 deletionsCHANGELOG.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,8 +94,10 @@ Resulting in a folder structure like the following:

## [0.4.0]

- Navigate through text content from previous levels.
-Want to look back at a previous lesson's content?Navigate through text content from previous levels by clicking the "Learn" dropdown.

![traverse content](./docs/images/traverse-content.png)

- Fixes progress navigation bug when no steps in a level
- Continue an incomplete tutorial started in the same workspace. Choose the "continue" path from the start screen. Progress is stored in local storage in the workspace.

![continue tutorial](./docs/images/continue-tutorial.png)
Binary file addeddocs/images/continue-tutorial.png
View file
Open in desktop
Loading
Sorry, something went wrong.Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 14 additions & 16 deletionssrc/channel/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,24 +75,22 @@ class Channel implements Channel {
// continue from tutorial from local storage
const tutorial: TT.Tutorial | null = this.context.tutorial.get()

// new tutorial
this.send({ type: 'START_NEW_TUTORIAL', payload: { env } })
return

// disable continue until fixed

// // set tutorial
// const { position, progress } = await this.context.setTutorial(this.workspaceState, tutorial)
// no stored tutorial, must start new tutorial
if (!tutorial || !tutorial.id) {
this.send({ type: 'START_NEW_TUTORIAL', payload: { env } })
return
}

// if (progress.complete) {
// // tutorial is already complete
// this.send({ type: 'TUTORIAL_ALREADY_COMPLETE', payload: { env } })
// return
// }
// // communicate to client the tutorial & stepProgress state
// this.send({ type: 'LOAD_STORED_TUTORIAL', payload: { env, tutorial, progress, position } })
// load continued tutorial position & progress
const { position, progress } = await this.context.setTutorial(this.workspaceState, tutorial)

// return
if (progress.complete) {
// tutorial is already complete
this.send({ type: 'TUTORIAL_ALREADY_COMPLETE', payload: { env } })
return
}
// communicate to client the tutorial & stepProgress state
this.send({ type: 'LOAD_STORED_TUTORIAL', payload: { env, tutorial, progress, position } })
} catch (e) {
const error = {
type: 'UnknownError',
Expand Down
12 changes: 8 additions & 4 deletionsweb-app/src/components/Router/index.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,14 +17,19 @@ declare let acquireVsCodeApi: any

const editor = acquireVsCodeApi()
const editorSend = (action: T.Action) => {
logger(`CLIENTTO EXT: "${action.type}"`)
logger(`TO EXT: "${action.type}"`)
return editor.postMessage(action)
}

// router finds first state match of <Route path='' />
const useRouter = (): Output => {
const [state, send] = useMachine<T.MachineContext, any>(createMachine({ editorSend }))

const sendWithLog = (action: T.Action): void => {
logger(`SEND: ${action.type}`, action)
send(action)
}

logger(`STATE: ${JSON.stringify(state.value)}`)

// event bus listener
Expand All@@ -38,8 +43,7 @@ const useRouter = (): Output => {
if (action.source) {
return
}
logger(`CLIENT RECEIVED: "${action.type}"`)
send(action)
sendWithLog(action)
}
window.addEventListener(listener, handler)
return () => {
Expand DownExpand Up@@ -74,7 +78,7 @@ const useRouter = (): Output => {

return {
context: state.context,
send,
send: sendWithLog,
Router,
Route,
}
Expand Down
6 changes: 5 additions & 1 deletionweb-app/src/containers/Start/index.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,7 +86,11 @@ interface ContainerProps {
const StartPageContainer = ({ context, send }: ContainerProps) => {
const tutorial = context.tutorial || undefined
return (
<StartPage onContinue={() => send('CONTINUE_TUTORIAL')} onNew={() => send('NEW_TUTORIAL')} tutorial={tutorial} />
<StartPage
onContinue={() => send({ type: 'CONTINUE_TUTORIAL' })}
onNew={() => send({ type: 'NEW_TUTORIAL' })}
tutorial={tutorial}
/>
)
}

Expand Down
52 changes: 52 additions & 0 deletionsweb-app/src/containers/Tutorial/ContentMenu.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
import * as React from 'react'
import * as T from 'typings'
import * as TT from 'typings/tutorial'
import { Menu } from '@alifd/next'
import Icon from '../../components/Icon'

interface Props {
tutorial: TT.Tutorial
position: T.Position
progress: T.Progress
setTitle: (title: string) => void
setContent: (content: string) => void
}

const ContentMenu = ({ tutorial, position, progress, setTitle, setContent }: Props) => {
const setMenuContent = (levelId: string) => {
const selectedLevel: TT.Level | undefined = tutorial.levels.find((l: TT.Level) => l.id === levelId)
if (selectedLevel) {
setTitle(selectedLevel.title)
setContent(selectedLevel.content)
}
}
return (
<Menu>
{tutorial.levels.map((level: TT.Level) => {
const isCurrent = level.id === position.levelId
const isComplete = progress.levels[level.id]
let icon
let disabled = false

if (isComplete) {
// completed icon
icon = <Icon type="minus" size="xs" />
} else if (isCurrent) {
// current icon`
icon = <Icon type="minus" size="xs" />
} else {
// upcoming
disabled = true
icon = <Icon type="lock" size="xs" />
}
return (
<Menu.Item key={level.id} disabled={disabled} onSelect={() => setMenuContent(level.id)}>
{icon}&nbsp;&nbsp;&nbsp;{level.title}
</Menu.Item>
)
})}
</Menu>
)
}

export default ContentMenu
55 changes: 12 additions & 43 deletionsweb-app/src/containers/Tutorial/index.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
import * as React from 'react'
import * as T from 'typings'
import * as TT from 'typings/tutorial'
import { Menu } from '@alifd/next'
import * as selectors from '../../services/selectors'
importIcon from '../../components/Icon'
importContentMenu from './ContentMenu'
import Level from './components/Level'
import logger from '../../services/logger'

interface PageProps {
context: T.MachineContext
Expand All@@ -23,9 +21,9 @@ const TutorialPage = (props: PageProps) => {

const onContinue = (): void => {
props.send({
type: 'LEVEL_NEXT',
type: 'NEXT_LEVEL',
payload: {
LevelId: position.levelId,
levelId: position.levelId,
},
})
}
Expand All@@ -45,48 +43,19 @@ const TutorialPage = (props: PageProps) => {
return { ...step, status }
})

const setMenuContent = (levelId: string) => {
const selectedLevel: TT.Level | undefined = tutorial.levels.find((l: TT.Level) => l.id === levelId)
if (selectedLevel) {
setTitle(selectedLevel.title)
setContent(selectedLevel.content)
}
}

const menu = (
<Menu>
{tutorial.levels.map((level: TT.Level) => {
const isCurrent = level.id === position.levelId
logger('progress', progress)
const isComplete = progress.levels[level.id]
let icon
let disabled = false

if (isComplete) {
// completed icon
icon = <Icon type="minus" size="xs" />
} else if (isCurrent) {
// current icon`
icon = <Icon type="minus" size="xs" />
} else {
// upcoming
disabled = true
icon = <Icon type="lock" size="xs" />
}
return (
<Menu.Item key={level.id} disabled={disabled} onSelect={() => setMenuContent(level.id)}>
{icon}&nbsp;&nbsp;&nbsp;{level.title}
</Menu.Item>
)
})}
</Menu>
)

return (
<Level
title={title}
content={content}
menu={menu}
menu={
<ContentMenu
tutorial={tutorial}
position={position}
progress={progress}
setTitle={setTitle}
setContent={setContent}
/>
}
index={tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId)}
steps={steps}
status={progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE'}
Expand Down
36 changes: 16 additions & 20 deletionsweb-app/src/services/state/actions/context.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ import * as TT from 'typings/tutorial'
import { assign, send, ActionFunctionMap } from 'xstate'
import * as selectors from '../../selectors'
import onError from '../../../services/sentry/onError'
import logger from '../../../services/logger'

const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
// @ts-ignore
Expand All@@ -15,25 +16,20 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
},
}),
// @ts-ignore
storeContinuedTutorial: assign({
env: (context: T.MachineContext, event: T.MachineEvent) => {
return {
loadContinuedTutorial: assign((context: T.MachineContext, event: T.MachineEvent): any =>{
return {
env: {
...context.env,
...event.payload.env,
}
},
tutorial: (context: T.MachineContext, event: T.MachineEvent) => {
return event.payload.tutorial
},
progress: (context: T.MachineContext, event: T.MachineEvent) => {
return event.payload.progress
},
position: (context: T.MachineContext, event: T.MachineEvent) => {
return event.payload.position
},
},
tutorial: event.payload.tutorial,
progress: event.payload.progress,
position: event.payload.position,
}
}),

// @ts-ignore
startNewTutorial: assign({
initProgressPosition: assign({
position: (context: T.MachineContext, event: T.MachineEvent): any => {
const position: T.Position = selectors.initialPosition(context)
return position
Expand DownExpand Up@@ -119,8 +115,7 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
// @ts-ignore
updatePosition: assign({
position: (context: T.MachineContext, event: T.MachineEvent): any => {
const { position } = event.payload
return position
return event.payload
},
}),
loadNext: send(
Expand All@@ -140,7 +135,7 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
// NEXT STEP
if (hasNextStep) {
const nextPosition = { ...position, stepId: steps[stepIndex + 1].id }
return { type: 'NEXT_STEP', payload:{ position:nextPosition } }
return { type: 'NEXT_STEP', payload: nextPosition }
}

// has next level?
Expand All@@ -164,7 +159,7 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
levelId: nextLevel.id,
stepId: nextLevel.steps[0].id,
}
return { type: 'NEXT_LEVEL', payload:{ position:nextPosition } }
return { type: 'NEXT_LEVEL', payload: nextPosition }
}

// COMPLETED
Expand DownExpand Up@@ -230,8 +225,9 @@ const contextActions: ActionFunctionMap<T.MachineContext, T.MachineEvent> = {
error: (): any => null,
}),
// @ts-ignore
checkEmptySteps: send((context: T.MachineContext) => {
checkLevelCompleted: send((context: T.MachineContext) => {
// no step id indicates no steps to complete
logger(context.position)
return {
type: context.position.stepId === null ? 'START_COMPLETED_LEVEL' : 'START_LEVEL',
}
Expand Down
12 changes: 6 additions & 6 deletionsweb-app/src/services/state/machine.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,7 +64,7 @@ export const createMachine = (options: any) => {
},
LOAD_STORED_TUTORIAL: {
target: 'Start',
actions: ['storeContinuedTutorial'],
actions: ['loadContinuedTutorial'],
},
START_NEW_TUTORIAL: {
target: 'Start',
Expand DownExpand Up@@ -97,7 +97,7 @@ export const createMachine = (options: any) => {
on: {
NEW_TUTORIAL: 'ValidateSetup',
CONTINUE_TUTORIAL: {
target: '#tutorial-level',
target: '#tutorial',
actions: ['continueConfig'],
},
CONTINUE_FAILED: {
Expand DownExpand Up@@ -127,7 +127,7 @@ export const createMachine = (options: any) => {
},
},
StartTutorial: {
onEntry: ['startNewTutorial'],
onEntry: ['initProgressPosition'],
after: {
0: '#tutorial',
},
Expand DownExpand Up@@ -157,7 +157,7 @@ export const createMachine = (options: any) => {
initial: 'Load',
states: {
Load: {
onEntry: ['loadLevel', 'loadStep', 'checkEmptySteps'],
onEntry: ['loadLevel', 'loadStep', 'checkLevelCompleted'],
on: {
START_LEVEL: 'Normal',
START_COMPLETED_LEVEL: 'LevelComplete',
Expand DownExpand Up@@ -214,9 +214,9 @@ export const createMachine = (options: any) => {
onEntry: ['updateLevelProgress'],
onExit: ['syncLevelProgress'],
on: {
LEVEL_NEXT: {
NEXT_LEVEL: {
target: '#tutorial-load-next',
actions: ['testClear'],
actions: ['testClear', 'updatePosition'],
},
},
},
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp