11import * as CR from 'typings'
2+ import * as G from 'typings/graphql'
23import * as vscode from 'vscode'
34
45import Storage from './services/storage'
56import tutorialConfig from './actions/tutorialConfig'
67import setupActions from './actions/setupActions'
78import solutionActions from './actions/solutionActions'
89
10+
911interface Channel {
1012receive ( action :CR . Action ) :Promise < void >
1113send ( action :CR . Action ) :Promise < void >
@@ -18,17 +20,25 @@ interface ChannelProps {
1820
1921class Channel implements Channel {
2022private postMessage :( action :CR . Action ) => Thenable < boolean >
21- private currentTutorial :Storage < { id : string | null , version : string | null } >
22- private stepProgress :Storage < CR . StepProgress > | undefined
23+ private currentTutorial :Storage < G . Tutorial | null >
24+ private stepProgress :Storage < CR . StepProgress >
2325private workspaceState :vscode . Memento
2426constructor ( { postMessage, workspaceState} :ChannelProps ) {
2527this . postMessage = postMessage
2628this . workspaceState = workspaceState
2729
28- this . currentTutorial = new Storage < { id :string | null , version :string | null } > ( {
30+ // local storage of current tutorial for continuing tutorials
31+ this . currentTutorial = new Storage < G . Tutorial | null > ( {
2932key :'coderoad:currentTutorial' ,
3033storage :workspaceState ,
31- defaultValue :{ id :null , version :null }
34+ defaultValue :null ,
35+ } )
36+
37+ // initialized for consistent typings. unused
38+ this . stepProgress = new Storage < CR . StepProgress > ( {
39+ key :'coderoad:stepProgress' ,
40+ storage :this . workspaceState ,
41+ defaultValue :{ }
3242} )
3343}
3444
@@ -38,39 +48,94 @@ class Channel implements Channel {
3848console . log ( 'RECEIVED:' , actionType )
3949switch ( actionType ) {
4050// continue from tutorial from local storage
41- case 'TUTORIAL_LOAD_STORED ' :
42- const tutorial = await this . currentTutorial . get ( )
51+ case 'EDITOR_TUTORIAL_LOAD ' :
52+ const tutorial : G . Tutorial | null = await this . currentTutorial . get ( )
4353
44- if ( tutorial && tutorial . id && tutorial . version ) {
45- this . stepProgress = new Storage < CR . StepProgress > ( {
46- key :`coderoad:stepProgress:${ tutorial . id } :${ tutorial . version } ` ,
47- storage :this . workspaceState ,
48- defaultValue :{ }
49- } )
50- const stepProgress = await this . stepProgress . get ( )
51- console . log ( 'looking at stored' )
52- console . log ( JSON . stringify ( tutorial ) )
53- console . log ( JSON . stringify ( stepProgress ) )
54- // communicate to client the tutorial & stepProgress state
55- this . send ( { type :'CONTINUE_TUTORIAL' , payload :{ tutorial, stepProgress} } )
56- } else {
54+ // new tutorial
55+ if ( ! tutorial || ! tutorial . id || ! tutorial . version ) {
5756this . send ( { type :'NEW_TUTORIAL' } )
57+ return
58+ }
59+
60+ // continue tutorial
61+ // setup progress for specific tutorial
62+ this . stepProgress = new Storage < CR . StepProgress > ( {
63+ key :`coderoad:stepProgress:${ tutorial . id } :${ tutorial . version } ` ,
64+ storage :this . workspaceState ,
65+ defaultValue :{ }
66+ } )
67+ const stepProgress = await this . stepProgress . get ( )
68+ console . log ( 'looking at stored' )
69+ console . log ( JSON . stringify ( tutorial ) )
70+ console . log ( JSON . stringify ( stepProgress ) )
71+ const progress :CR . Progress = {
72+ steps :stepProgress ,
73+ stages :{ } ,
74+ levels :{ } ,
75+ complete :false
76+ }
77+
78+ const position :CR . Position = {
79+ stepId :'' ,
80+ stageId :'' ,
81+ levelId :'' ,
5882}
5983
84+ // calculate progress from tutorial & stepProgress
85+ for ( const level of tutorial . version . levels ) {
86+ for ( const stage of level . stages ) {
87+ // set stage progress
88+ const stageComplete :boolean = stage . steps . every ( ( step :G . Step ) => {
89+ return stepProgress [ step . id ]
90+ } )
91+ if ( stageComplete ) {
92+ progress . stages [ stage . id ] = true
93+ } else if ( ! position . stageId . length ) {
94+ // set stage amd step position
95+ position . stageId = stage . id
96+ //@ts -ignore
97+ position . stepId = stage . steps . find ( ( step :G . Step ) => ! stepProgress [ step . id ] ) . id
98+ }
99+ }
100+ // set level progress
101+ const levelComplete :boolean = level . stages . every ( ( stage :G . Stage ) => {
102+ return progress . stages [ stage . id ]
103+ } )
104+ if ( levelComplete ) {
105+ progress . levels [ level . id ] = true
106+ } else if ( ! position . levelId . length ) {
107+ position . levelId = level . id
108+ }
109+ }
110+ // set tutorial progress
111+ progress . complete = tutorial . version . levels . every ( ( level :G . Level ) => {
112+ return progress . levels [ level . id ]
113+ } )
114+ // communicate to client the tutorial & stepProgress state
115+ this . send ( { type :'CONTINUE_TUTORIAL' , payload :{ tutorial, progress, position} } )
116+
60117return
61118// clear tutorial local storage
62119case 'TUTORIAL_CLEAR' :
63- this . currentTutorial . set ( { id : null , version : null } )
120+ this . currentTutorial . set ( null )
64121
65122// reset tutorial progress on clear
66- if ( this . stepProgress ) {
67- this . stepProgress . set ( { } )
68- }
123+ this . stepProgress . set ( { } )
69124return
70125// configure test runner, language, git
71- case 'TUTORIAL_CONFIG' :
72- tutorialConfig ( action . payload )
73- this . currentTutorial . set ( action . payload )
126+ case 'EDITOR_TUTORIAL_CONFIG' :
127+ const tutorialInfo = action . payload . tutorial
128+ console . log ( 'tutorialConfig' , JSON . stringify ( tutorialInfo ) )
129+ if ( ! this . stepProgress ) {
130+ // setup progress for new tutorials
131+ this . stepProgress = new Storage < CR . StepProgress > ( {
132+ key :`coderoad:stepProgress:${ tutorialInfo . id } :${ tutorialInfo . version . version } ` ,
133+ storage :this . workspaceState ,
134+ defaultValue :{ }
135+ } )
136+ }
137+ tutorialConfig ( tutorialInfo )
138+ this . currentTutorial . set ( tutorialInfo )
74139return
75140// run unit tests on step
76141case 'TEST_RUN' :
@@ -97,10 +162,9 @@ class Channel implements Channel {
97162switch ( action . type ) {
98163case 'TEST_PASS' :
99164// update local storage stepProgress
100- // stepProgress.update({
101- // [action.payload.stepId]: true
102- // })
103- return
165+ this . stepProgress . update ( {
166+ [ action . payload . stepId ] :true
167+ } )
104168}
105169
106170const success = await this . postMessage ( action )