diff --git a/src/actions/__tests__/workspaces.ts b/src/actions/__tests__/workspaces.ts index a25d00e5b7..c655281ba9 100755 --- a/src/actions/__tests__/workspaces.ts +++ b/src/actions/__tests__/workspaces.ts @@ -6,6 +6,7 @@ import { beginClearContext, browseReplHistoryDown, browseReplHistoryUp, + changeChapter, changeEditorHeight, changeEditorWidth, changeExternalLibrary, @@ -20,6 +21,7 @@ import { evalRepl, evalTestcase, externalLibrarySelect, + fetchChapter, highlightEditorLine, moveCursor, navigateToDeclaration, @@ -29,6 +31,7 @@ import { setEditorBreakpoint, toggleEditorAutorun, updateActiveTab, + updateChapter, updateCurrentAssessmentId, updateCurrentSubmissionId, updateEditorValue, @@ -417,3 +420,36 @@ test('moveCursor generates correct action object', () => { } }); }); + +test('fetchChapter generates correct action object', () => { + const action = fetchChapter(); + expect(action).toEqual({ + type: actionTypes.FETCH_CHAPTER + }); +}); + +test('changeChapter generates correct action object', () => { + const chapter = 1; + const variant = 'default'; + const action = changeChapter(chapter, variant); + expect(action).toEqual({ + type: actionTypes.CHANGE_CHAPTER, + payload: { + chapter, + variant + } + }); +}); + +test('updateChapter generates correct action object', () => { + const chapter = 1; + const variant = 'default'; + const action = updateChapter(chapter, variant); + expect(action).toEqual({ + type: actionTypes.UPDATE_CHAPTER, + payload: { + chapter, + variant + } + }); +}); diff --git a/src/actions/actionTypes.ts b/src/actions/actionTypes.ts index d0dfb7a8b2..40d7922be3 100755 --- a/src/actions/actionTypes.ts +++ b/src/actions/actionTypes.ts @@ -59,6 +59,9 @@ export const UPDATE_EDITOR_BREAKPOINTS = 'UPDATE_EDITOR_BREAKPOINTS'; export const UPDATE_HAS_UNSAVED_CHANGES = 'UPDATE_HAS_UNSAVED_CHANGES'; export const UPDATE_REPL_VALUE = 'UPDATE_REPL_VALUE'; export const UPDATE_WORKSPACE = 'UPDATE_WORKSPACE'; +export const FETCH_CHAPTER = 'FETCH_CHAPTER'; +export const UPDATE_CHAPTER = 'UPDATE_CHAPTER'; +export const CHANGE_CHAPTER = 'CHANGE_CHAPTER'; /** Collab Editing */ export const INIT_INVITE = 'INIT_INVITE'; diff --git a/src/actions/workspaces.ts b/src/actions/workspaces.ts index 0e98afbc1a..9ee2e291ca 100755 --- a/src/actions/workspaces.ts +++ b/src/actions/workspaces.ts @@ -216,6 +216,14 @@ export const updateHasUnsavedChanges = ( hasUnsavedChanges }); +export const fetchChapter = () => action(actionTypes.FETCH_CHAPTER); + +export const changeChapter = (chapter: number, variant: Variant) => + action(actionTypes.CHANGE_CHAPTER, { chapter, variant }); + +export const updateChapter = (chapter: number, variant: Variant) => + action(actionTypes.UPDATE_CHAPTER, { chapter, variant }); + export const promptAutocomplete = ( workspaceLocation: WorkspaceLocation, row: number, diff --git a/src/components/Playground.tsx b/src/components/Playground.tsx index de2324e465..14d518c6bf 100755 --- a/src/components/Playground.tsx +++ b/src/components/Playground.tsx @@ -89,6 +89,7 @@ export interface IDispatchProps { handleDebuggerResume: () => void; handleDebuggerReset: () => void; handleToggleEditorAutorun: () => void; + handleFetchChapter: () => void; handlePromptAutocomplete: (row: number, col: number, callback: any) => void; } @@ -111,6 +112,7 @@ class Playground extends React.Component { }; this.handlers.goGreen = this.toggleIsGreen.bind(this); (window as any).thePlayground = this; + this.props.handleFetchChapter(); } public render() { diff --git a/src/components/__tests__/Playground.tsx b/src/components/__tests__/Playground.tsx index 37f778655e..363c7aa7db 100755 --- a/src/components/__tests__/Playground.tsx +++ b/src/components/__tests__/Playground.tsx @@ -58,6 +58,7 @@ const baseProps = { handleDebuggerPause: () => {}, handleDebuggerResume: () => {}, handleDebuggerReset: () => {}, + handleFetchChapter: () => {}, handlePromptAutocomplete: (row: number, col: number, callback: any) => {} }; diff --git a/src/components/academy/DefaultChapter.tsx b/src/components/academy/DefaultChapter.tsx new file mode 100644 index 0000000000..cdf5e689e0 --- /dev/null +++ b/src/components/academy/DefaultChapter.tsx @@ -0,0 +1,76 @@ +import { Button, Classes, MenuItem } from '@blueprintjs/core'; +import { IconNames } from '@blueprintjs/icons'; +import { ItemRenderer, Select } from '@blueprintjs/select'; + +import * as React from 'react'; + +import { RouteComponentProps } from 'react-router'; + +import { Variant } from 'js-slang/dist/types'; +import { ISourceLanguage, sourceLanguages, styliseChapter } from '../../reducers/states'; + +export interface IChapterProps extends IDispatchProps, IStateProps, RouteComponentProps<{}> {} + +export type IDispatchProps = { + handleFetchChapter: () => void; + handleUpdateChapter: (chapter: IChapter) => void; + handleChapterSelect?: (i: IChapter, e: React.ChangeEvent) => void; +}; + +export interface IStateProps { + sourceChapter: number; + sourceVariant: Variant; +} + +export interface IChapter { + chapter: number; + variant: Variant; + displayName: string; +} + +export function DefaultChapter(props: IChapterProps) { + props.handleFetchChapter(); + + const chapters = sourceLanguages.map((lang: ISourceLanguage) => { + return { + chapter: lang.chapter, + variant: lang.variant, + displayName: styliseChapter(lang.chapter, lang.variant) + }; + }); + + const chapterRenderer: ItemRenderer = (lang, { handleClick }) => ( + + ); + + const ChapterSelectComponent = Select.ofType(); + + const chapSelect = ( + currentChap: number, + currentVariant: Variant, + handleSelect = (i: IChapter) => {} + ) => ( + +