Skip to content

Commit 4a6d6f7

Browse files
authored
Merge pull request #388 from coderoad/feature/on-reset
Feature/on reset
2 parents db94db6 + 98c7c50 commit 4a6d6f7

16 files changed

+194
-76
lines changed

src/channel/index.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import saveCommit from '../actions/saveCommit'
88
import { setupActions, solutionActions } from '../actions/setupActions'
99
import tutorialConfig from '../actions/tutorialConfig'
1010
import { COMMANDS } from '../editor/commands'
11-
import logger from '../services/logger'
1211
import Context from './context'
13-
import { version, compareVersions } from '../services/dependencies'
14-
import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace'
1512
import { readFile } from 'fs'
1613
import { join } from 'path'
1714
import { promisify } from 'util'
15+
import logger from '../services/logger'
16+
import { version, compareVersions } from '../services/dependencies'
17+
import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace'
1818
import { showOutput } from '../services/testRunner/output'
19+
import { exec } from '../services/node'
1920
import { WORKSPACE_ROOT, TUTORIAL_URL } from '../environment'
2021

2122
const readFileAsync = promisify(readFile)
@@ -319,6 +320,17 @@ class Channel implements Channel {
319320
case 'EDITOR_RUN_TEST':
320321
vscode.commands.executeCommand(COMMANDS.RUN_TEST, action?.payload)
321322
return
323+
case 'EDITOR_RUN_RESET_SCRIPT':
324+
const tutorial: TT.Tutorial | null = this.context.tutorial.get()
325+
// if tutorial.config.reset.command, run it
326+
if (tutorial?.config?.reset?.command) {
327+
await exec({ command: tutorial.config.reset.command })
328+
}
329+
return
330+
case 'EDITOR_RUN_RESET_TO_LAST_PASS':
331+
return
332+
case 'EDITOR_RUN_RESET_TO_TIMELINE':
333+
return
322334
default:
323335
logger(`No match for action type: ${actionType}`)
324336
return

src/services/git/lastPass.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as TT from '../../../typings/tutorial'
2+
import * as T from '../../../typings'
3+
4+
const getLastPassCommitHash = (position: T.Position, levels: TT.Level[]) => {
5+
// get previous position
6+
const { levelId, stepId } = position
7+
8+
// get solution hash if it exists
9+
// else get setup hash
10+
}
11+
12+
export default getLastPassCommitHash

typings/tutorial.d.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@ import { ProgressStatus } from './index'
22

33
export type Maybe<T> = T | null
44

5+
export type ConfigReset = {
6+
command?: string
7+
}
8+
59
export type TutorialConfig = {
6-
appVersions: TutorialAppVersions
10+
appVersions?: TutorialAppVersions
711
testRunner: TestRunnerConfig
812
repo: TutorialRepo
913
dependencies?: TutorialDependency[]
14+
reset?: ConfigReset
1015
}
1116

1217
/** Logical groupings of tasks */

web-app/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"react-addons-css-transition-group": "^15.6.2",
4040
"react-dom": "^16.13.1",
4141
"reselect": "^4.0.0",
42+
"use-media": "^1.4.0",
4243
"xstate": "^4.11.0"
4344
},
4445
"devDependencies": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as React from 'react'
2+
import { Dialog } from '@alifd/next'
3+
import Button from '../../../components/Button'
4+
import Markdown from '../../../components/Markdown'
5+
6+
interface Props {
7+
disabled: boolean
8+
onReset(): void
9+
}
10+
11+
const Reset = (props: Props) => {
12+
const [modalState, setModalState] = React.useState<'none' | 'confirm' | 'progress'>('none')
13+
14+
const onClose = () => {
15+
setModalState('none')
16+
}
17+
18+
const onOk = () => {
19+
setModalState('progress')
20+
props.onReset()
21+
return setTimeout(() => {
22+
setModalState('none')
23+
}, 3000)
24+
}
25+
26+
return (
27+
<>
28+
<Button type="secondary" size="medium" onClick={() => setModalState('confirm')} disabled={props.disabled}>
29+
Reset
30+
</Button>
31+
<Dialog
32+
title="Reset"
33+
visible={modalState === 'confirm'}
34+
onOk={onOk}
35+
onCancel={onClose}
36+
onClose={onClose}
37+
footerActions={['ok', 'cancel']}
38+
>
39+
<Markdown>
40+
{`Are you sure you want to reset your progress?
41+
Resetting progress will remove the commits you have made and replace them with the tutorial commit timeline. Your code may look different after resetting.`}
42+
</Markdown>
43+
</Dialog>
44+
<Dialog
45+
title="Resetting..."
46+
visible={modalState === 'progress'}
47+
footer={false}
48+
onClose={onClose}
49+
closeable={false}
50+
>
51+
Reverting progress to an earlier commit...
52+
</Dialog>
53+
</>
54+
)
55+
}
56+
57+
export default Reset
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from 'react'
2+
import { Progress } from '@alifd/next'
3+
import useMedia from 'use-media'
4+
5+
const styles = {
6+
progress: {
7+
display: 'flex' as 'flex',
8+
justifyContent: 'flex-end' as 'flex-end',
9+
alignItems: 'center' as 'center',
10+
width: '10rem',
11+
color: 'white',
12+
},
13+
text: { color: 'white' },
14+
}
15+
16+
interface Props {
17+
current: number
18+
max: number
19+
}
20+
21+
const StepProgress = (props: Props) => {
22+
const Text = (
23+
<span style={styles.text}>
24+
{props.current} of {props.max}
25+
</span>
26+
)
27+
28+
const isWide = useMedia({ minWidth: '340px' })
29+
30+
if (isWide) {
31+
return (
32+
<Progress
33+
state="success"
34+
progressive
35+
percent={(props.current / props.max) * 100}
36+
shape="line"
37+
color="rgb(85, 132, 255)"
38+
css={styles.progress}
39+
textRender={() => {
40+
return Text
41+
}}
42+
/>
43+
)
44+
}
45+
return <div css={{ marginRight: '0.5rem', fontSize: '80%' }}>{Text}</div>
46+
}
47+
48+
export default StepProgress

web-app/src/containers/Tutorial/index.tsx

+19-33
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import * as selectors from '../../services/selectors'
44
import SideMenu from './components/SideMenu'
55
import Level from './components/Level'
66
import Icon from '../../components/Icon'
7-
import SettingsPage from './containers/Settings'
87
import ReviewPage from './containers/Review'
98
import Button from '../../components/Button'
109
import ProcessMessages from '../../components/ProcessMessages'
1110
import TestMessage from '../../components/TestMessage'
12-
import { Progress } from '@alifd/next'
11+
import StepProgress from './components/StepProgress'
1312
import { DISPLAY_RUN_TEST_BUTTON } from '../../environment'
1413
import formatLevels from './formatLevels'
14+
// import SettingsPage from './containers/Settings'
15+
// import Reset from './components/Reset'
1516

1617
const styles = {
1718
header: {
@@ -47,13 +48,6 @@ const styles = {
4748
right: 0,
4849
color: 'white',
4950
},
50-
taskProgress: {
51-
display: 'flex' as 'flex',
52-
justifyContent: 'flex-end' as 'flex-end',
53-
alignItems: 'center' as 'center',
54-
width: '10rem',
55-
color: 'white',
56-
},
5751
processes: {
5852
padding: '0 1rem',
5953
position: 'fixed' as 'fixed',
@@ -100,6 +94,10 @@ const TutorialPage = (props: PageProps) => {
10094
props.send({ type: 'RUN_TEST' })
10195
}
10296

97+
const onReset = (): void => {
98+
// TODO
99+
}
100+
103101
const [menuVisible, setMenuVisible] = React.useState(false)
104102

105103
const [page, setPage] = React.useState<'level' | 'settings' | 'review'>('level')
@@ -140,39 +138,27 @@ const TutorialPage = (props: PageProps) => {
140138
</div>
141139
)}
142140
{/* Left */}
143-
{DISPLAY_RUN_TEST_BUTTON && level.status !== 'COMPLETE' ? (
144-
<Button style={{ marginLeft: '1rem' }} type="primary" onClick={onRunTest} disabled={processes.length > 0}>
145-
Run
146-
</Button>
147-
) : (
148-
<div />
149-
)}
141+
<div css={{ flex: 1 }}>
142+
{DISPLAY_RUN_TEST_BUTTON && level.status !== 'COMPLETE' ? (
143+
<Button style={{ marginLeft: '1rem' }} type="primary" onClick={onRunTest} disabled={processes.length > 0}>
144+
Run
145+
</Button>
146+
) : null}
147+
</div>
150148

151149
{/* Center */}
152-
<div />
150+
<div css={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
151+
{/* <Reset onReset={onReset} disabled={processes.length > 0} /> */}
152+
</div>
153153

154154
{/* Right */}
155-
<div>
155+
<div css={{ flex: 1, display: 'flex', justifyContent: 'flex-end' }}>
156156
{level.status === 'COMPLETE' || !level.steps.length ? (
157157
<Button style={{ marginRight: '1rem' }} type="primary" onClick={onContinue}>
158158
Continue
159159
</Button>
160160
) : (
161-
<Progress
162-
state="success"
163-
progressive
164-
percent={(stepIndex / level.steps.length) * 100}
165-
shape="line"
166-
color="rgb(85, 132, 255)"
167-
css={styles.taskProgress}
168-
textRender={() => {
169-
return (
170-
<span style={{ color: 'white' }}>
171-
{stepIndex} of {level.steps.length}
172-
</span>
173-
)
174-
}}
175-
/>
161+
<StepProgress current={stepIndex} max={level.steps.length} />
176162
)}
177163
</div>
178164
</div>

web-app/src/services/state/actions/editor.ts

+5
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,9 @@ export default (editorSend: any) => ({
117117
payload: { position: context.position },
118118
})
119119
},
120+
runResetScript() {
121+
editorSend({
122+
type: 'EDITOR_RUN_RESET_SCRIPT',
123+
})
124+
},
120125
})

web-app/src/services/state/machine.ts

+3
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ export const createMachine = (options: any) => {
168168
RUN_TEST: {
169169
actions: ['runTest'],
170170
},
171+
RESET_SCRIPT: {
172+
actions: ['runResetScript'],
173+
},
171174
},
172175
},
173176
TestRunning: {

web-app/stories/Review.stories.tsx

+1-12
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,5 @@ storiesOf('Review', module)
142142
.addDecorator(SideBarDecorator)
143143
.addDecorator(withKnobs)
144144
.add('Example', () => {
145-
const progress = {
146-
levels: {
147-
'1': true,
148-
},
149-
steps: {
150-
'1.1': true,
151-
'1.2': true,
152-
'1.3': true,
153-
'2.1': true,
154-
},
155-
}
156-
return <Review levels={levels} progress={progress} />
145+
return <Review levels={levels} />
157146
})

web-app/stories/Tests.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ import SideBarDecorator from './utils/SideBarDecorator'
55

66
storiesOf('Test Message', module)
77
.addDecorator(SideBarDecorator)
8-
.add('Fail', () => <TestMessage content={'Test failed for some reason'} />)
8+
.add('Fail', () => <TestMessage message={'Test failed for some reason'} />)

0 commit comments

Comments
 (0)