Skip to content

Commit 54b5428

Browse files
authored
Merge pull request #296 from coderoad/traverse-content
Traverse content (blocked)
2 parents 38a474f + 965064e commit 54b5428

File tree

8 files changed

+176
-45
lines changed

8 files changed

+176
-45
lines changed

Diff for: src/channel/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ class Channel implements Channel {
297297
vscode.commands.executeCommand(COMMANDS.RUN_TEST)
298298
return
299299

300+
case 'EDITOR_SYNC_PROGRESS':
301+
// update progress when a level is deemed complete in the client
302+
await this.context.progress.syncProgress(action.payload.progress)
303+
return
304+
300305
default:
301306
logger(`No match for action type: ${actionType}`)
302307
return

Diff for: src/channel/state/Progress.ts

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class Progress {
3939
public reset = () => {
4040
this.set(defaultValue)
4141
}
42+
public syncProgress = (progress: T.Progress): T.Progress => {
43+
const next = { ...this.value, ...progress }
44+
return this.set(next)
45+
}
4246
public setStepComplete = (tutorial: TT.Tutorial, stepId: string): T.Progress => {
4347
const next = this.value
4448
// mark step complete

Diff for: web-app/src/containers/Tutorial/components/Level.tsx

+47-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as React from 'react'
22
import * as T from 'typings'
33
import * as TT from 'typings/tutorial'
44
import { css, jsx } from '@emotion/core'
5+
import { Dropdown } from '@alifd/next'
6+
import Icon from '../../../components/Icon'
57
import Button from '../../../components/Button'
68
import Markdown from '../../../components/Markdown'
79
import ProcessMessages from '../../../components/ProcessMessages'
@@ -22,12 +24,19 @@ const styles = {
2224
paddingBottom: '5rem',
2325
},
2426
header: {
27+
display: 'flex' as 'flex',
28+
alignItems: 'center',
29+
justifyContent: 'space-between',
2530
height: '2rem',
2631
backgroundColor: '#EBEBEB',
2732
fontSize: '1rem',
2833
lineHeight: '1rem',
2934
padding: '10px 1rem',
3035
},
36+
learn: {
37+
textDecoration: 'none',
38+
color: 'inherit',
39+
},
3140
text: {
3241
padding: '0rem 1rem',
3342
paddingBottom: '1rem',
@@ -77,18 +86,34 @@ const styles = {
7786
}
7887

7988
interface Props {
80-
level: TT.Level & { status: T.ProgressStatus; index: number; steps: Array<TT.Step & { status: T.ProgressStatus }> }
89+
menu: any
90+
steps: Array<TT.Step & { status: T.ProgressStatus }>
91+
title: string
92+
index: number
93+
content: string
94+
status: 'COMPLETE' | 'ACTIVE' | 'INCOMPLETE'
8195
processes: T.ProcessEvent[]
8296
testStatus: T.TestStatus | null
8397
onContinue(): void
8498
onLoadSolution(): void
8599
}
86100

87-
const Level = ({ level, onContinue, onLoadSolution, processes, testStatus }: Props) => {
101+
const Level = ({
102+
menu,
103+
steps,
104+
title,
105+
content,
106+
index,
107+
status,
108+
onContinue,
109+
onLoadSolution,
110+
processes,
111+
testStatus,
112+
}: Props) => {
88113
// @ts-ignore
89-
let currentStep = level.steps.findIndex((s) => s.status === 'ACTIVE')
114+
let currentStep = steps.findIndex((s) => s.status === 'ACTIVE')
90115
if (currentStep === -1) {
91-
currentStep = level.steps.length
116+
currentStep = steps.length
92117
}
93118

94119
const pageBottomRef = React.useRef(null)
@@ -103,18 +128,27 @@ const Level = ({ level, onContinue, onLoadSolution, processes, testStatus }: Pro
103128
<div css={styles.page}>
104129
<div css={styles.content}>
105130
<div css={styles.header}>
106-
<span>Learn</span>
131+
<Dropdown
132+
trigger={
133+
<a css={styles.learn}>
134+
Learn <Icon type="arrow-down" size="xxs" />
135+
</a>
136+
}
137+
triggerType="click"
138+
>
139+
{menu}
140+
</Dropdown>
107141
</div>
108142
<div css={styles.text}>
109-
<h2 css={styles.title}>{level.title}</h2>
110-
<Markdown>{level.content || ''}</Markdown>
143+
<h2 css={styles.title}>{title}</h2>
144+
<Markdown>{content || ''}</Markdown>
111145
</div>
112146

113-
{level.steps.length ? (
147+
{steps.length ? (
114148
<div css={styles.tasks}>
115149
<div css={styles.header}>Tasks</div>
116150
<div css={styles.steps}>
117-
{level.steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, index: number) => {
151+
{steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, index: number) => {
118152
if (!step) {
119153
return null
120154
}
@@ -146,17 +180,17 @@ const Level = ({ level, onContinue, onLoadSolution, processes, testStatus }: Pro
146180

147181
<div css={styles.footer}>
148182
<span>
149-
{typeof level.index === 'number' ? `${level.index + 1}. ` : ''}
150-
{level.title}
183+
{typeof index === 'number' ? `${index + 1}. ` : ''}
184+
{title}
151185
</span>
152186
<span>
153-
{level.status === 'COMPLETE' || !level.steps.length ? (
187+
{status === 'COMPLETE' || !steps.length ? (
154188
<Button type="primary" onClick={onContinue}>
155189
Continue
156190
</Button>
157191
) : (
158192
<span css={styles.taskCount}>
159-
{currentStep} of {level.steps.length} tasks
193+
{currentStep} of {steps.length} tasks
160194
</span>
161195
)}
162196
</span>

Diff for: web-app/src/containers/Tutorial/index.tsx

+58-19
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import * as React from 'react'
22
import * as T from 'typings'
33
import * as TT from 'typings/tutorial'
4+
import { Menu } from '@alifd/next'
45
import * as selectors from '../../services/selectors'
6+
import Icon from '../../components/Icon'
57
import Level from './components/Level'
8+
import logger from '../../services/logger'
69

710
interface PageProps {
811
context: T.MachineContext
@@ -15,6 +18,9 @@ const TutorialPage = (props: PageProps) => {
1518
const tutorial = selectors.currentTutorial(props.context)
1619
const levelData: TT.Level = selectors.currentLevel(props.context)
1720

21+
const [title, setTitle] = React.useState<string>(levelData.title)
22+
const [content, setContent] = React.useState<string>(levelData.content)
23+
1824
const onContinue = (): void => {
1925
props.send({
2026
type: 'LEVEL_NEXT',
@@ -28,29 +34,62 @@ const TutorialPage = (props: PageProps) => {
2834
props.send({ type: 'STEP_SOLUTION_LOAD' })
2935
}
3036

31-
const level: TT.Level & {
32-
status: T.ProgressStatus
33-
index: number
34-
steps: Array<TT.Step & { status: T.ProgressStatus }>
35-
} = {
36-
...levelData,
37-
index: tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId),
38-
status: progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE',
39-
steps: levelData.steps.map((step: TT.Step) => {
40-
// label step status for step component
41-
let status: T.ProgressStatus = 'INCOMPLETE'
42-
if (progress.steps[step.id]) {
43-
status = 'COMPLETE'
44-
} else if (step.id === position.stepId) {
45-
status = 'ACTIVE'
46-
}
47-
return { ...step, status }
48-
}),
37+
const steps = levelData.steps.map((step: TT.Step) => {
38+
// label step status for step component
39+
let status: T.ProgressStatus = 'INCOMPLETE'
40+
if (progress.steps[step.id]) {
41+
status = 'COMPLETE'
42+
} else if (step.id === position.stepId) {
43+
status = 'ACTIVE'
44+
}
45+
return { ...step, status }
46+
})
47+
48+
const setMenuContent = (levelId: string) => {
49+
const selectedLevel: TT.Level | undefined = tutorial.levels.find((l: TT.Level) => l.id === levelId)
50+
if (selectedLevel) {
51+
setTitle(selectedLevel.title)
52+
setContent(selectedLevel.content)
53+
}
4954
}
5055

56+
const menu = (
57+
<Menu>
58+
{tutorial.levels.map((level: TT.Level) => {
59+
const isCurrent = level.id === position.levelId
60+
logger('progress', progress)
61+
const isComplete = progress.levels[level.id]
62+
let icon
63+
let disabled = false
64+
65+
if (isComplete) {
66+
// completed icon
67+
icon = <Icon type="minus" size="xs" />
68+
} else if (isCurrent) {
69+
// current icon`
70+
icon = <Icon type="minus" size="xs" />
71+
} else {
72+
// upcoming
73+
disabled = true
74+
icon = <Icon type="lock" size="xs" />
75+
}
76+
return (
77+
<Menu.Item key={level.id} disabled={disabled} onSelect={() => setMenuContent(level.id)}>
78+
{icon}&nbsp;&nbsp;&nbsp;{level.title}
79+
</Menu.Item>
80+
)
81+
})}
82+
</Menu>
83+
)
84+
5185
return (
5286
<Level
53-
level={level}
87+
title={title}
88+
content={content}
89+
menu={menu}
90+
index={tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId)}
91+
steps={steps}
92+
status={progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE'}
5493
onContinue={onContinue}
5594
onLoadSolution={onLoadSolution}
5695
processes={processes}

Diff for: web-app/src/environment.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ for (const required of requiredKeys) {
99
export const DEBUG: boolean = (process.env.REACT_APP_DEBUG || '').toLowerCase() === 'true'
1010
export const VERSION: string = process.env.VERSION || 'unknown'
1111
export const NODE_ENV: string = process.env.NODE_ENV || 'development'
12-
export const LOG: boolean =
13-
(process.env.REACT_APP_LOG || '').toLowerCase() === 'true' && process.env.NODE_ENV !== 'production'
12+
export const LOG: boolean = (process.env.REACT_APP_LOG || '').toLowerCase() === 'true'
1413
export const TUTORIAL_LIST_URL: string = process.env.REACT_APP_TUTORIAL_LIST_URL || ''
1514
export const SENTRY_DSN: string | null = process.env.REACT_APP_SENTRY_DSN || null

Diff for: web-app/src/services/state/actions/editor.ts

+8
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ export default (editorSend: any) => ({
7474
})
7575
}
7676
},
77+
syncLevelProgress(context: CR.MachineContext): void {
78+
editorSend({
79+
type: 'EDITOR_SYNC_PROGRESS',
80+
payload: {
81+
progress: context.progress,
82+
},
83+
})
84+
},
7785
clearStorage(): void {
7886
editorSend({ type: 'TUTORIAL_CLEAR' })
7987
},

Diff for: web-app/src/services/state/machine.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,12 @@ export const createMachine = (options: any) => {
207207
target: 'Normal',
208208
actions: ['loadStep'],
209209
},
210-
LEVEL_COMPLETE: {
211-
target: 'LevelComplete',
212-
actions: ['updateLevelProgress'],
213-
},
210+
LEVEL_COMPLETE: 'LevelComplete',
214211
},
215212
},
216213
LevelComplete: {
214+
onEntry: ['updateLevelProgress'],
215+
onExit: ['syncLevelProgress'],
217216
on: {
218217
LEVEL_NEXT: {
219218
target: '#tutorial-load-next',

0 commit comments

Comments
 (0)