Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Commit 8f1954c

Browse files
committedApr 25, 2016
save progress to localStorage
·
v0.13.3v0.8.0
1 parent 0b1ffd7 commit 8f1954c

File tree

32 files changed

+186
-141
lines changed

32 files changed

+186
-141
lines changed
 

‎lib/actions/_types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ exports.HINT_POSITION_SET = 'HINT_POSITION_SET';
88
exports.HINT_SHOW = 'HINT_SHOW';
99
exports.PACKAGE_SET = 'PACKAGE_SET';
1010
exports.PAGE_SET = 'PAGE_SET';
11+
exports.POSITION_LOAD = 'POSITION_LOAD';
1112
exports.POSITION_SET = 'POSITION_SET';
1213
exports.PROGRESS_LOAD = 'PROGRESS_LOAD';
1314
exports.ROUTE_SET = 'ROUTE_SET';

‎lib/actions/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var page_1 = require('./page');
1414
exports.pageSet = page_1.pageSet;
1515
exports.pageNext = page_1.pageNext;
1616
var position_1 = require('./position');
17+
exports.positionLoad = position_1.positionLoad;
1718
exports.positionSet = position_1.positionSet;
1819
var route_1 = require('./route');
1920
exports.routeSet = route_1.routeSet;

‎lib/actions/position.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"use strict";
22
var _types_1 = require('./_types');
3+
function positionLoad() {
4+
return { type: _types_1.POSITION_LOAD };
5+
}
6+
exports.positionLoad = positionLoad;
37
function positionSet(position) {
48
return {
59
payload: { position: position },

‎lib/actions/progress.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
"use strict";
22
var _types_1 = require('./_types');
3+
var position_1 = require('./position');
34
var store_1 = require('../store');
45
function progressLoad() {
6+
setTimeout(function () {
7+
store_1.default.dispatch(position_1.positionLoad());
8+
});
59
return { type: _types_1.PROGRESS_LOAD };
610
}
711
exports.progressLoad = progressLoad;
12+
function isTrue(x) {
13+
return x === true;
14+
}
815
function completePage() {
916
var position = store_1.default.getState().position;
10-
var pageLength = store_1.default.getState().progress.chapters[position.chapter].pages.length;
11-
if (position.page >= pageLength - 1) {
17+
var chapter = store_1.default.getState().progress.chapters[position.chapter];
18+
if (chapter.pages.every(function (x) { return x; })) {
1219
store_1.default.dispatch(completeChapter());
1320
}
1421
return {
@@ -19,8 +26,8 @@ function completePage() {
1926
exports.completePage = completePage;
2027
function completeChapter() {
2128
var chapter = store_1.default.getState().position.chapter;
22-
var chapterLength = store_1.default.getState().progress.chapters.length;
23-
if (chapter >= chapterLength - 1) {
29+
var progress = store_1.default.getState().progress;
30+
if (progress.chapters.every(function (x) { return x.completed; })) {
2431
store_1.default.dispatch(completeTutorial());
2532
}
2633
return {

‎lib/components/Page/Hints/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var help_1 = require('material-ui/svg-icons/action/help');
77
var styles = {
88
position: 'relative',
99
margin: '-5px 20px',
10+
right: '10px',
1011
width: '360px',
1112
textAlign: 'center',
1213
zIndex: '0',

‎lib/components/Page/PageToolbar/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ var styles = {
1111
right: '0px',
1212
height: '60px',
1313
width: '400px',
14+
margin: '0px',
1415
};
1516
exports.PageToolbar = function (_a) {
1617
var tasks = _a.tasks, taskPosition = _a.taskPosition, children = _a.children;

‎lib/components/Progress/ProgressChapter/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ var descriptionStyles = {
1010
fontSize: '14px'
1111
};
1212
exports.ProgressChapter = function (_a) {
13-
var chapter = _a.chapter, chapterIndex = _a.chapterIndex, position = _a.position;
13+
var progress = _a.progress, chapter = _a.chapter, chapterIndex = _a.chapterIndex, position = _a.position;
1414
var isActive = chapterIndex === position.chapter;
15-
return (React.createElement(List_1.ListItem, {key: chapterIndex, className: isActive ? 'isActive' : null, style: styles, initiallyOpen: chapterIndex === 0, primaryTogglesNestedList: chapterIndex === position.chapter && !chapter.completed, nestedItems: chapter.pages.map(function (page, pageIndex) { return (React.createElement(ProgressPage_1.ProgressPage, {key: pageIndex, pageIndex: pageIndex, page: page, chapterIndex: chapterIndex, position: position})); })}, React.createElement("h3", null, chapterIndex + 1, ". ", chapter.title), React.createElement("span", {style: descriptionStyles}, React.createElement(index_1.Markdown, null, chapter.description))));
15+
return (React.createElement(List_1.ListItem, {key: chapterIndex, className: isActive ? 'isActive' : null, style: styles, initiallyOpen: chapterIndex === 0, primaryTogglesNestedList: chapterIndex === position.chapter && !progress.chapters[chapterIndex].completed, nestedItems: chapter.pages.map(function (page, pageIndex) { return (React.createElement(ProgressPage_1.ProgressPage, {key: pageIndex, pageIndex: pageIndex, page: page, chapterIndex: chapterIndex, position: position, progress: progress})); })}, React.createElement("h3", null, chapterIndex + 1, ". ", chapter.title), React.createElement("span", {style: descriptionStyles}, React.createElement(index_1.Markdown, null, chapter.description))));
1616
};

‎lib/components/Progress/ProgressPage/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,19 @@ var ProgressPage = (function (_super) {
2929
_super.apply(this, arguments);
3030
}
3131
ProgressPage.prototype.canActivate = function (isActive) {
32-
var _a = this.props, chapterIndex = _a.chapterIndex, pageIndex = _a.pageIndex, position = _a.position;
33-
var earlierChapter = chapterIndex < position.chapter;
32+
var _a = this.props, chapterIndex = _a.chapterIndex, pageIndex = _a.pageIndex, position = _a.position, progress = _a.progress;
33+
var completed = progress.chapters[chapterIndex].pages[pageIndex];
3434
var currentChapter = chapterIndex === position.chapter;
3535
var earlierOrCurrentPage = pageIndex <= position.page;
36-
return isActive || earlierChapter ||
36+
return isActive || completed ||
3737
(currentChapter && earlierOrCurrentPage);
3838
};
3939
ProgressPage.prototype.render = function () {
40-
var _a = this.props, page = _a.page, position = _a.position, chapterIndex = _a.chapterIndex, pageIndex = _a.pageIndex, selectPage = _a.selectPage;
40+
var _a = this.props, page = _a.page, position = _a.position, chapterIndex = _a.chapterIndex, pageIndex = _a.pageIndex, progress = _a.progress, selectPage = _a.selectPage;
4141
var isActive = chapterIndex === position.chapter && pageIndex === position.page;
4242
var canActivate = this.canActivate(isActive);
43-
return (React.createElement(List_1.ListItem, {key: pageIndex, style: Object.assign({}, styles, !canActivate ? { color: colors_1.grey400 } : {}), primaryText: (pageIndex + 1) + ". " + page.title, secondaryText: canActivate ? page.description : '', leftIcon: progressIcon_1.progressIcon(page.completed, isActive), onClick: canActivate
43+
var completed = progress.chapters[chapterIndex].pages[pageIndex];
44+
return (React.createElement(List_1.ListItem, {key: pageIndex, style: Object.assign({}, styles, !canActivate ? { color: colors_1.grey400 } : {}), primaryText: (pageIndex + 1) + ". " + page.title, secondaryText: canActivate ? page.description : '', leftIcon: progressIcon_1.progressIcon(completed, isActive), onClick: canActivate
4445
? selectPage.bind(this, {
4546
chapter: chapterIndex,
4647
page: pageIndex

‎lib/components/Progress/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ var pageStyle = {
99
margin: '0px',
1010
};
1111
exports.Progress = function (_a) {
12-
var progress = _a.progress, position = _a.position, info = _a.info;
13-
return (React.createElement(Paper_1.default, {style: pageStyle}, React.createElement(List_1.List, null, React.createElement(Subheader_1.default, null, info.title), progress.chapters.map(function (chapter, chapterIndex) { return (React.createElement(ProgressChapter_1.ProgressChapter, {key: chapterIndex, chapter: chapter, chapterIndex: chapterIndex, position: position})); }))));
12+
var progress = _a.progress, position = _a.position, info = _a.info, tutorial = _a.tutorial;
13+
return (React.createElement(Paper_1.default, {style: pageStyle}, React.createElement(List_1.List, null, React.createElement(Subheader_1.default, null, info.name), tutorial.chapters.map(function (chapter, chapterIndex) { return (React.createElement(ProgressChapter_1.ProgressChapter, {key: chapterIndex, chapter: chapter, chapterIndex: chapterIndex, position: position, progress: progress})); }))));
1414
};

‎lib/components/mount.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

‎lib/reducers/position/index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
"use strict";
22
var _types_1 = require('../../actions/_types');
3+
var store_1 = require('../../store');
34
var _position = {
45
chapter: 0,
56
page: 0,
67
};
78
function positionReducer(position, action) {
89
if (position === void 0) { position = _position; }
910
switch (action.type) {
11+
case _types_1.POSITION_LOAD:
12+
var chapters = store_1.default.getState().progress.chapters;
13+
var chapter = chapters.indexOf(function (x) { return !x.completed; });
14+
if (chapter < 0) {
15+
chapter = chapters.length - 1;
16+
}
17+
var progressPage = chapters[chapter].pages;
18+
var page = progressPage.indexOf(function (x) { return !x; });
19+
if (page < 0) {
20+
page = progressPage.length - 1;
21+
}
22+
return { chapter: chapter, page: page };
1023
case _types_1.PAGE_SET:
1124
case _types_1.POSITION_SET:
1225
return action.payload.position;

‎lib/reducers/progress/index.js

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,43 @@
11
"use strict";
22
var _types_1 = require('../../actions/_types');
3+
var local_storage_1 = require('./local-storage');
34
var store_1 = require('../../store');
45
var _progress = {
56
completed: false,
6-
chapters: [{
7-
title: '',
8-
description: '',
9-
completed: false,
10-
pages: [{
11-
title: '',
12-
description: '',
13-
completed: false,
14-
}]
15-
}]
7+
chapters: []
168
};
179
function progressReducer(progress, action) {
1810
if (progress === void 0) { progress = _progress; }
1911
switch (action.type) {
2012
case _types_1.PROGRESS_LOAD:
21-
var chapters = store_1.default.getState().tutorial.chapters;
13+
var tutorial = store_1.default.getState().tutorial;
14+
var saved = local_storage_1.loadProgressFromLocalStorage();
15+
if (saved) {
16+
return saved;
17+
}
2218
return {
2319
completed: false,
24-
chapters: !chapters ? [] : chapters.map(function (_a) {
25-
var title = _a.title, description = _a.description, completed = _a.completed, pages = _a.pages;
26-
return {
27-
title: title, description: description, completed: completed || false,
28-
pages: !pages ? [] : pages.map(function (page) {
29-
return {
30-
title: page.title,
31-
description: page.description,
32-
completed: page.completed || false,
33-
};
34-
})
35-
};
36-
})
20+
chapters: !tutorial.chapters
21+
? []
22+
: tutorial.chapters.map(function (chapter) {
23+
return {
24+
completed: false,
25+
pages: chapter.pages.map(function () { return false; })
26+
};
27+
})
3728
};
3829
case _types_1.COMPLETE_PAGE:
3930
var position = action.payload.position;
40-
progress.chapters[position.chapter].pages[position.page].completed = true;
31+
progress.chapters[position.chapter].pages[position.page] = true;
32+
local_storage_1.saveToLocalStorage(progress);
4133
return progress;
4234
case _types_1.COMPLETE_CHAPTER:
4335
progress.chapters[action.payload.chapter].completed = true;
36+
local_storage_1.saveToLocalStorage(progress);
4437
return progress;
4538
case _types_1.COMPLETE_TUTORIAL:
4639
progress.completed = true;
40+
local_storage_1.saveToLocalStorage(progress);
4741
return progress;
4842
default:
4943
return progress;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"use strict";
2+
var store_1 = require('../../store');
3+
function getLocalStorageKey() {
4+
return 'coderoad:' + store_1.default.getState().tutorial.name;
5+
}
6+
function saveToLocalStorage(progress) {
7+
try {
8+
window.localStorage
9+
.setItem(getLocalStorageKey(), JSON.stringify(progress));
10+
}
11+
catch (e) {
12+
console.log('Error saving progress:', e);
13+
}
14+
}
15+
exports.saveToLocalStorage = saveToLocalStorage;
16+
function loadProgressFromLocalStorage() {
17+
var savedProgress = JSON.parse(window.localStorage.getItem(getLocalStorageKey()) || null);
18+
if (savedProgress) {
19+
return savedProgress;
20+
}
21+
return null;
22+
}
23+
exports.loadProgressFromLocalStorage = loadProgressFromLocalStorage;

‎lib/store/localStorage.js

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎lib/store/middleware.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
var env = 'dev';
33
var redux_1 = require('redux');
44
var redux_thunk_1 = require('redux-thunk');
5-
var localStorage_1 = require('./localStorage');
65
var middlewares = [redux_thunk_1.default];
76
if (env && env === 'dev') {
87
var createLogger = require('redux-logger');
98
var logger = createLogger();
109
middlewares.push(logger);
1110
}
12-
var createStoreWithMiddleware = redux_1.compose(redux_1.applyMiddleware.apply(void 0, middlewares), localStorage_1.default)(redux_1.createStore);
11+
var createStoreWithMiddleware = redux_1.compose(redux_1.applyMiddleware.apply(void 0, middlewares))(redux_1.createStore);
1312
Object.defineProperty(exports, "__esModule", { value: true });
1413
exports.default = createStoreWithMiddleware;

‎package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@
4747
"react-redux": "4.4.5",
4848
"react-tap-event-plugin": "1.0.0",
4949
"redux": "3.5.2",
50-
"redux-localstorage": "^1.0.0-rc4",
51-
"redux-localstorage-filter": "^0.1.1",
5250
"redux-logger": "2.6.1",
5351
"redux-thunk": "2.0.1"
5452
},

‎src/actions/_types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const HINT_POSITION_SET = 'HINT_POSITION_SET';
77
export const HINT_SHOW = 'HINT_SHOW';
88
export const PACKAGE_SET = 'PACKAGE_SET';
99
export const PAGE_SET = 'PAGE_SET';
10+
export const POSITION_LOAD = 'POSITION_LOAD';
1011
export const POSITION_SET = 'POSITION_SET';
1112
export const PROGRESS_LOAD = 'PROGRESS_LOAD';
1213
export const ROUTE_SET = 'ROUTE_SET';

‎src/actions/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export {
44
} from './progress';
55
export {hintShow, hintPositionSet} from './hint';
66
export {pageSet, pageNext} from './page';
7-
export {positionSet} from './position';
7+
export {positionLoad, positionSet} from './position';
88
export {routeSet} from './route';
99
export {setupVerify} from './setup';
1010
export {

‎src/actions/position.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import {POSITION_SET} from './_types';
1+
import {POSITION_SET, POSITION_LOAD} from './_types';
2+
3+
export function positionLoad() {
4+
return { type: POSITION_LOAD };
5+
}
26

37
export function positionSet(position: CR.Position): Action {
48
return {

‎src/actions/progress.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
import {
22
PROGRESS_LOAD, COMPLETE_PAGE, COMPLETE_CHAPTER, COMPLETE_TUTORIAL
33
} from './_types';
4+
import {positionLoad} from './position';
45
import store from '../store';
56

67
export function progressLoad(): Action {
8+
setTimeout(function() {
9+
store.dispatch(positionLoad());
10+
});
711
return { type: PROGRESS_LOAD };
812
}
913

14+
function isTrue(x) {
15+
return x === true;
16+
}
17+
1018
export function completePage(): Action {
1119
const position: CR.Position = store.getState().position;
12-
const pageLength: number = store.getState().progress.chapters[position.chapter].pages.length;
13-
if (position.page >= pageLength - 1) {
20+
const chapter = store.getState().progress.chapters[position.chapter];
21+
// all pages are true, chapter complete
22+
if (chapter.pages.every(x => x)) {
1423
store.dispatch(completeChapter());
1524
}
1625
return {
@@ -21,8 +30,9 @@ export function completePage(): Action {
2130

2231
export function completeChapter(): Action {
2332
const chapter: number = store.getState().position.chapter;
24-
const chapterLength: number = store.getState().progress.chapters.length;
25-
if (chapter >= chapterLength - 1) {
33+
const progress = store.getState().progress;
34+
// all chapters complete, tutorial complete
35+
if (progress.chapters.every(x => x.completed)) {
2636
store.dispatch(completeTutorial());
2737
}
2838
return {

‎src/components/Page/Hints/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Help from 'material-ui/svg-icons/action/help';
77
const styles = {
88
position: 'relative',
99
margin: '-5px 20px',
10+
right: '10px',
1011
width: '360px',
1112
textAlign: 'center',
1213
zIndex: '0',

‎src/components/Page/PageToolbar/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const styles = {
1111
right: '0px',
1212
height: '60px',
1313
width: '400px',
14+
margin: '0px',
1415
};
1516

1617
export const PageToolbar: React.StatelessComponent<{

‎src/components/Progress/ProgressChapter/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ const descriptionStyles = {
1313
};
1414

1515
export const ProgressChapter: React.StatelessComponent<{
16-
chapter: CR.Chapter, chapterIndex: number, position: CR.Position
17-
}> = ({chapter, chapterIndex, position}) => {
16+
progress: CR.Progress, chapter: CR.Chapter,
17+
chapterIndex: number, position: CR.Position
18+
}> = ({progress, chapter, chapterIndex, position}) => {
1819
const isActive = chapterIndex === position.chapter;
1920
return (
2021
<ListItem
@@ -23,7 +24,7 @@ export const ProgressChapter: React.StatelessComponent<{
2324
style={styles}
2425
initiallyOpen={chapterIndex === 0}
2526
primaryTogglesNestedList={
26-
chapterIndex === position.chapter && !chapter.completed
27+
chapterIndex === position.chapter && !progress.chapters[chapterIndex].completed
2728
}
2829
nestedItems={
2930
chapter.pages.map((page: CR.Page, pageIndex: number) => (
@@ -33,6 +34,7 @@ export const ProgressChapter: React.StatelessComponent<{
3334
page={page}
3435
chapterIndex={chapterIndex}
3536
position={position}
37+
progress={progress}
3638
/>
3739
))
3840
}

‎src/components/Progress/ProgressPage/index.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,28 @@ const styles = {
2121
};
2222
})
2323
export class ProgressPage extends React.Component<{
24-
page: CR.Page, chapterIndex: number,
24+
page: CR.Page, chapterIndex: number, progress: CR.Progress,
2525
position: CR.Position, pageIndex: number, selectPage?: () => void}, {}> {
2626
canActivate(isActive: boolean) {
27-
const {chapterIndex, pageIndex, position} = this.props;
28-
const earlierChapter = chapterIndex < position.chapter;
27+
const {chapterIndex, pageIndex, position, progress} = this.props;
28+
const completed = progress.chapters[chapterIndex].pages[pageIndex];
2929
const currentChapter = chapterIndex === position.chapter;
3030
const earlierOrCurrentPage = pageIndex <= position.page;
31-
return isActive || earlierChapter ||
31+
return isActive || completed ||
3232
(currentChapter && earlierOrCurrentPage);
3333
}
3434
render() {
35-
const {page, position, chapterIndex, pageIndex, selectPage} = this.props;
35+
const {page, position, chapterIndex, pageIndex, progress, selectPage} = this.props;
3636
const isActive = chapterIndex === position.chapter && pageIndex === position.page;
3737
const canActivate = this.canActivate(isActive);
38+
const completed = progress.chapters[chapterIndex].pages[pageIndex];
3839
return (
3940
<ListItem
4041
key={pageIndex}
4142
style={Object.assign({}, styles, !canActivate ? {color: grey400} : {})}
4243
primaryText={`${pageIndex + 1}. ${page.title}`}
4344
secondaryText={canActivate ? page.description : ''}
44-
leftIcon={progressIcon(page.completed, isActive)}
45+
leftIcon={progressIcon(completed, isActive)}
4546
onClick={
4647
canActivate
4748
? selectPage.bind(this, {

‎src/components/Progress/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ const pageStyle = {
1010
};
1111

1212
export const Progress: React.StatelessComponent<{
13-
progress: CR.Progress, position: CR.Position, info: Tutorial.Info
14-
}> = ({progress, position, info}) => (
13+
progress: CR.Progress, position: CR.Position,
14+
info: Tutorial.Info, tutorial: CR.Tutorial
15+
}> = ({progress, position, info, tutorial}) => (
1516
<Paper style={pageStyle}>
1617
<List>
17-
<Subheader>{info.title}</Subheader>
18-
{progress.chapters.map((chapter: CR.Chapter, chapterIndex: number) => (
18+
<Subheader>{info.name}</Subheader>
19+
{tutorial.chapters.map((chapter: CR.Chapter, chapterIndex: number) => (
1920
<ProgressChapter
2021
key={chapterIndex}
2122
chapter={chapter}
2223
chapterIndex={chapterIndex}
2324
position={position}
25+
progress={progress}
2426
/>
2527
))}
2628
</List>

‎src/reducers/position/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
2-
PAGE_SET, POSITION_SET
2+
PAGE_SET, POSITION_SET, POSITION_LOAD
33
} from '../../actions/_types';
4+
import store from '../../store';
45

56
const _position: CR.Position = {
67
chapter: 0,
@@ -11,6 +12,18 @@ export default function positionReducer(
1112
position = _position, action: Action
1213
): CR.Position {
1314
switch (action.type) {
15+
case POSITION_LOAD:
16+
const chapters = store.getState().progress.chapters;
17+
let chapter = chapters.indexOf(x => !x.completed);
18+
if (chapter < 0) {
19+
chapter = chapters.length - 1;
20+
}
21+
const progressPage = chapters[chapter].pages;
22+
let page = progressPage.indexOf(x => !x);
23+
if (page < 0) {
24+
page = progressPage.length - 1;
25+
}
26+
return { chapter, page };
1427
case PAGE_SET:
1528
case POSITION_SET:
1629
return action.payload.position;

‎src/reducers/progress/index.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,47 @@
11
import {
22
PROGRESS_LOAD, COMPLETE_PAGE, COMPLETE_CHAPTER, COMPLETE_TUTORIAL
33
} from '../../actions/_types';
4-
// import TutorialPackage from '../../services/tutorial-package';
4+
import {loadProgressFromLocalStorage, saveToLocalStorage} from './local-storage';
55
import store from '../../store';
66

77
const _progress: CR.Progress = {
88
completed: false,
9-
chapters: [{
10-
title: '',
11-
description: '',
12-
completed: false,
13-
pages: [{
14-
title: '',
15-
description: '',
16-
completed: false,
17-
}]
18-
}]
9+
chapters: []
1910
};
2011

2112
export default function progressReducer(
2213
progress = _progress, action: Action
2314
): CR.Progress {
2415
switch (action.type) {
2516
case PROGRESS_LOAD:
26-
const chapters = store.getState().tutorial.chapters;
17+
const tutorial = store.getState().tutorial;
18+
// load saved progress
19+
const saved = loadProgressFromLocalStorage();
20+
if (saved) { return saved; }
21+
// set progress defaults
2722
return {
2823
completed: false,
29-
chapters: !chapters ? [] : chapters.map(({title, description, completed, pages}) => {
30-
return {
31-
title, description, completed: completed || false,
32-
pages: !pages ? [] : pages.map((page: CR.Page) => {
33-
return {
34-
title: page.title,
35-
description: page.description,
36-
completed: page.completed || false,
37-
};
38-
})
39-
};
40-
})
24+
chapters: !tutorial.chapters
25+
? []
26+
: tutorial.chapters.map((chapter) => {
27+
return {
28+
completed: false,
29+
pages: chapter.pages.map(() => false)
30+
};
31+
})
4132
};
4233
case COMPLETE_PAGE:
4334
const position = action.payload.position;
44-
progress.chapters[position.chapter].pages[position.page].completed = true;
35+
progress.chapters[position.chapter].pages[position.page] = true;
36+
saveToLocalStorage(progress);
4537
return progress;
4638
case COMPLETE_CHAPTER:
4739
progress.chapters[action.payload.chapter].completed = true;
40+
saveToLocalStorage(progress);
4841
return progress;
4942
case COMPLETE_TUTORIAL:
5043
progress.completed = true;
44+
saveToLocalStorage(progress);
5145
return progress;
5246
default:
5347
return progress;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import store from '../../store';
2+
3+
function getLocalStorageKey() {
4+
return 'coderoad:' + store.getState().tutorial.name;
5+
}
6+
7+
export function saveToLocalStorage(progress: CR.Progress): void {
8+
try {
9+
window.localStorage
10+
.setItem(getLocalStorageKey(), JSON.stringify(progress));
11+
} catch (e) {
12+
console.log('Error saving progress:', e);
13+
}
14+
}
15+
16+
export function loadProgressFromLocalStorage() {
17+
const savedProgress: CR.Progress = JSON.parse(
18+
window.localStorage.getItem(getLocalStorageKey()) || null
19+
);
20+
if (savedProgress) {
21+
return savedProgress;
22+
}
23+
return null;
24+
}

‎src/store/localStorage.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

‎src/store/middleware.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const env = 'dev'; // toggle on/off logger
22

33
import {createStore, compose, applyMiddleware} from 'redux';
44
import thunk from 'redux-thunk';
5-
import localStorage from './localStorage';
65

76
const middlewares = [thunk];
87

@@ -13,8 +12,7 @@ if (env && env === 'dev') {
1312
}
1413

1514
const createStoreWithMiddleware = compose(
16-
applyMiddleware(...middlewares),
17-
localStorage
15+
applyMiddleware(...middlewares)
1816
)(createStore);
1917

2018
export default createStoreWithMiddleware;

‎src/typings/cr/cr.d.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,8 @@ interface Position {
5959
interface Progress {
6060
completed: boolean;
6161
chapters: {
62-
title: string;
63-
description: string;
6462
completed: boolean;
65-
pages: {
66-
title: string;
67-
description: string;
68-
completed: boolean;
69-
}[]
63+
pages: boolean[];
7064
}[];
7165
}
7266

‎tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"src/reducers/page/index.ts",
8989
"src/reducers/position/index.ts",
9090
"src/reducers/progress/index.ts",
91+
"src/reducers/progress/local-storage.ts",
9192
"src/reducers/route/index.ts",
9293
"src/reducers/task-position/index.ts",
9394
"src/reducers/task-tests/index.ts",
@@ -108,7 +109,6 @@
108109
"src/services/polyfills.ts",
109110
"src/services/system.ts",
110111
"src/store/index.ts",
111-
"src/store/localStorage.ts",
112112
"src/store/middleware.ts",
113113
"src/components/Alert/index.tsx",
114114
"src/components/App.tsx",

0 commit comments

Comments
 (0)
This repository has been archived.