Skip to content

Commit 3f929bd

Browse files
CP3108 Staff Dashboard - Playground Default Source Version Selector (#1073)
* Added Dropdown to change Default Source version * Added some tests * Run check format * Changed position of dropdown * Fixed syntax error * Fixed syntax error * Modified variant state * Modified fetchChapter Co-authored-by: Low Jun Kai, Sean <[email protected]>
1 parent 3b71b0f commit 3f929bd

File tree

14 files changed

+255
-0
lines changed

14 files changed

+255
-0
lines changed

src/actions/__tests__/workspaces.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
beginClearContext,
77
browseReplHistoryDown,
88
browseReplHistoryUp,
9+
changeChapter,
910
changeEditorHeight,
1011
changeEditorWidth,
1112
changeExternalLibrary,
@@ -20,6 +21,7 @@ import {
2021
evalRepl,
2122
evalTestcase,
2223
externalLibrarySelect,
24+
fetchChapter,
2325
highlightEditorLine,
2426
moveCursor,
2527
navigateToDeclaration,
@@ -29,6 +31,7 @@ import {
2931
setEditorBreakpoint,
3032
toggleEditorAutorun,
3133
updateActiveTab,
34+
updateChapter,
3235
updateCurrentAssessmentId,
3336
updateCurrentSubmissionId,
3437
updateEditorValue,
@@ -417,3 +420,36 @@ test('moveCursor generates correct action object', () => {
417420
}
418421
});
419422
});
423+
424+
test('fetchChapter generates correct action object', () => {
425+
const action = fetchChapter();
426+
expect(action).toEqual({
427+
type: actionTypes.FETCH_CHAPTER
428+
});
429+
});
430+
431+
test('changeChapter generates correct action object', () => {
432+
const chapter = 1;
433+
const variant = 'default';
434+
const action = changeChapter(chapter, variant);
435+
expect(action).toEqual({
436+
type: actionTypes.CHANGE_CHAPTER,
437+
payload: {
438+
chapter,
439+
variant
440+
}
441+
});
442+
});
443+
444+
test('updateChapter generates correct action object', () => {
445+
const chapter = 1;
446+
const variant = 'default';
447+
const action = updateChapter(chapter, variant);
448+
expect(action).toEqual({
449+
type: actionTypes.UPDATE_CHAPTER,
450+
payload: {
451+
chapter,
452+
variant
453+
}
454+
});
455+
});

src/actions/actionTypes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export const UPDATE_EDITOR_BREAKPOINTS = 'UPDATE_EDITOR_BREAKPOINTS';
5959
export const UPDATE_HAS_UNSAVED_CHANGES = 'UPDATE_HAS_UNSAVED_CHANGES';
6060
export const UPDATE_REPL_VALUE = 'UPDATE_REPL_VALUE';
6161
export const UPDATE_WORKSPACE = 'UPDATE_WORKSPACE';
62+
export const FETCH_CHAPTER = 'FETCH_CHAPTER';
63+
export const UPDATE_CHAPTER = 'UPDATE_CHAPTER';
64+
export const CHANGE_CHAPTER = 'CHANGE_CHAPTER';
6265

6366
/** Collab Editing */
6467
export const INIT_INVITE = 'INIT_INVITE';

src/actions/workspaces.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ export const updateHasUnsavedChanges = (
216216
hasUnsavedChanges
217217
});
218218

219+
export const fetchChapter = () => action(actionTypes.FETCH_CHAPTER);
220+
221+
export const changeChapter = (chapter: number, variant: Variant) =>
222+
action(actionTypes.CHANGE_CHAPTER, { chapter, variant });
223+
224+
export const updateChapter = (chapter: number, variant: Variant) =>
225+
action(actionTypes.UPDATE_CHAPTER, { chapter, variant });
226+
219227
export const promptAutocomplete = (
220228
workspaceLocation: WorkspaceLocation,
221229
row: number,

src/components/Playground.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export interface IDispatchProps {
8989
handleDebuggerResume: () => void;
9090
handleDebuggerReset: () => void;
9191
handleToggleEditorAutorun: () => void;
92+
handleFetchChapter: () => void;
9293
handlePromptAutocomplete: (row: number, col: number, callback: any) => void;
9394
}
9495

@@ -111,6 +112,7 @@ class Playground extends React.Component<IPlaygroundProps, PlaygroundState> {
111112
};
112113
this.handlers.goGreen = this.toggleIsGreen.bind(this);
113114
(window as any).thePlayground = this;
115+
this.props.handleFetchChapter();
114116
}
115117

116118
public render() {

src/components/__tests__/Playground.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const baseProps = {
5858
handleDebuggerPause: () => {},
5959
handleDebuggerResume: () => {},
6060
handleDebuggerReset: () => {},
61+
handleFetchChapter: () => {},
6162
handlePromptAutocomplete: (row: number, col: number, callback: any) => {}
6263
};
6364

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Button, Classes, MenuItem } from '@blueprintjs/core';
2+
import { IconNames } from '@blueprintjs/icons';
3+
import { ItemRenderer, Select } from '@blueprintjs/select';
4+
5+
import * as React from 'react';
6+
7+
import { RouteComponentProps } from 'react-router';
8+
9+
import { Variant } from 'js-slang/dist/types';
10+
import { ISourceLanguage, sourceLanguages, styliseChapter } from '../../reducers/states';
11+
12+
export interface IChapterProps extends IDispatchProps, IStateProps, RouteComponentProps<{}> {}
13+
14+
export type IDispatchProps = {
15+
handleFetchChapter: () => void;
16+
handleUpdateChapter: (chapter: IChapter) => void;
17+
handleChapterSelect?: (i: IChapter, e: React.ChangeEvent<HTMLSelectElement>) => void;
18+
};
19+
20+
export interface IStateProps {
21+
sourceChapter: number;
22+
sourceVariant: Variant;
23+
}
24+
25+
export interface IChapter {
26+
chapter: number;
27+
variant: Variant;
28+
displayName: string;
29+
}
30+
31+
export function DefaultChapter(props: IChapterProps) {
32+
props.handleFetchChapter();
33+
34+
const chapters = sourceLanguages.map((lang: ISourceLanguage) => {
35+
return {
36+
chapter: lang.chapter,
37+
variant: lang.variant,
38+
displayName: styliseChapter(lang.chapter, lang.variant)
39+
};
40+
});
41+
42+
const chapterRenderer: ItemRenderer<IChapter> = (lang, { handleClick }) => (
43+
<MenuItem
44+
active={false}
45+
key={lang.chapter + lang.variant}
46+
onClick={handleClick}
47+
text={lang.displayName}
48+
/>
49+
);
50+
51+
const ChapterSelectComponent = Select.ofType<IChapter>();
52+
53+
const chapSelect = (
54+
currentChap: number,
55+
currentVariant: Variant,
56+
handleSelect = (i: IChapter) => {}
57+
) => (
58+
<ChapterSelectComponent
59+
className={Classes.MINIMAL}
60+
items={chapters}
61+
onItemSelect={handleSelect}
62+
itemRenderer={chapterRenderer}
63+
filterable={false}
64+
>
65+
<Button
66+
className={Classes.MINIMAL}
67+
text={styliseChapter(currentChap, currentVariant)}
68+
rightIcon={IconNames.DOUBLE_CARET_VERTICAL}
69+
/>
70+
</ChapterSelectComponent>
71+
);
72+
73+
return (
74+
<div> {chapSelect(props.sourceChapter, props.sourceVariant, props.handleUpdateChapter)} </div>
75+
);
76+
}

src/components/academy/NavigationBar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { AssessmentCategories } from '../assessment/assessmentShape';
1111
import NotificationBadge from '../../containers/notification/NotificationBadge';
1212
import { filterNotificationsByType } from '../notification/NotificationHelpers';
1313

14+
import DefaultChapter from '../../containers/DefaultChapterContainer';
15+
1416
type OwnProps = {
1517
role: Role;
1618
};
@@ -81,6 +83,8 @@ const NavigationBar: React.SFC<OwnProps> = props => (
8183
</NavbarGroup>
8284
{props.role === Role.Admin || props.role === Role.Staff ? (
8385
<NavbarGroup align={Alignment.RIGHT}>
86+
<DefaultChapter />
87+
8488
<NavLink
8589
to={'/academy/dashboard'}
8690
activeClassName={Classes.ACTIVE}

src/components/academy/__tests__/__snapshots__/NavigationBar.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ exports[`Grading NavLink renders for Role.Admin 1`] = `
8080
</NavLink>
8181
</Blueprint3.NavbarGroup>
8282
<Blueprint3.NavbarGroup align=\\"right\\">
83+
<withRouter(Connect(DefaultChapter)) />
8384
<NavLink to=\\"/academy/dashboard\\" activeClassName=\\"bp3-active\\" className=\\"NavigationBar__link bp3-button bp3-minimal\\" aria-current=\\"page\\">
8485
<Blueprint3.Icon icon=\\"globe\\" />
8586
<div className=\\"navbar-button-text hidden-xs\\">
@@ -148,6 +149,7 @@ exports[`Grading NavLink renders for Role.Staff 1`] = `
148149
</NavLink>
149150
</Blueprint3.NavbarGroup>
150151
<Blueprint3.NavbarGroup align=\\"right\\">
152+
<withRouter(Connect(DefaultChapter)) />
151153
<NavLink to=\\"/academy/dashboard\\" activeClassName=\\"bp3-active\\" className=\\"NavigationBar__link bp3-button bp3-minimal\\" aria-current=\\"page\\">
152154
<Blueprint3.Icon icon=\\"globe\\" />
153155
<div className=\\"navbar-button-text hidden-xs\\">
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
2+
import { withRouter } from 'react-router';
3+
import { bindActionCreators, Dispatch } from 'redux';
4+
5+
import { changeChapter, fetchChapter } from '../actions';
6+
7+
import { DefaultChapter, IDispatchProps, IStateProps } from '../components/academy/DefaultChapter';
8+
import { IChapter } from '../components/workspace/controlBar';
9+
import { IState } from '../reducers/states';
10+
11+
const mapStateToProps: MapStateToProps<IStateProps, {}, IState> = state => ({
12+
sourceChapter: state.workspaces.playground.context.chapter,
13+
sourceVariant: state.workspaces.playground.context.variant
14+
});
15+
16+
const mapDispatchToProps: MapDispatchToProps<IDispatchProps, {}> = (dispatch: Dispatch<any>) =>
17+
bindActionCreators(
18+
{
19+
handleFetchChapter: () => fetchChapter(),
20+
handleUpdateChapter: (chapter: IChapter) => changeChapter(chapter.chapter, chapter.variant)
21+
},
22+
dispatch
23+
);
24+
25+
export default withRouter(
26+
connect(
27+
mapStateToProps,
28+
mapDispatchToProps
29+
)(DefaultChapter)
30+
);

src/containers/PlaygroundContainer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
evalEditor,
2020
evalRepl,
2121
externalLibrarySelect,
22+
fetchChapter,
2223
finishInvite,
2324
generateLzString,
2425
initInvite,
@@ -111,6 +112,7 @@ const mapDispatchToProps: MapDispatchToProps<IDispatchProps, {}> = (dispatch: Di
111112
handleDebuggerPause: () => beginDebuggerPause(workspaceLocation),
112113
handleDebuggerResume: () => debuggerResume(workspaceLocation),
113114
handleDebuggerReset: () => debuggerReset(workspaceLocation),
115+
handleFetchChapter: () => fetchChapter(),
114116
handlePromptAutocomplete: (row: number, col: number, callback: any) =>
115117
promptAutocomplete(workspaceLocation, row, col, callback)
116118
},

0 commit comments

Comments
 (0)