Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Functioning IDE for the playground #19

Merged
merged 143 commits into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
143 commits
Select commit Hold shift + click to select a range
de9df9b
Add button for playground at Navbar
ning-y May 14, 2018
42d4cb6
Make first NavbarGroup's align left explicit
ning-y May 14, 2018
e917cf0
Change playground icon
remo5000 May 14, 2018
c00bfeb
Add routes to Playground
ning-y May 14, 2018
c70d46a
Update test snapshots
ning-y May 14, 2018
0ab401a
Fix bad test for Playground component
ning-y May 14, 2018
c9de874
Add react-ace for IDE
ning-y May 14, 2018
b4f37b7
Try passing props into playground
ning-y May 15, 2018
c1d11a6
Load a preset "Hello World" onto the ace editor.
remo5000 May 15, 2018
8145a2a
Remove unused onChange()
remo5000 May 15, 2018
c8add20
Add stored state for playground editor text
remo5000 May 15, 2018
48bd369
Change initialValue prop to editorValue
remo5000 May 15, 2018
023f277
Made playground actions a separate file
ning-y May 15, 2018
dd585f9
Modify actions and dispatch call
remo5000 May 15, 2018
053b2c9
Change redux import statement
remo5000 May 15, 2018
b17cb25
Add IPlaygroundState to IState in index reducer
remo5000 May 15, 2018
8d480a3
Add playground reducer
remo5000 May 15, 2018
7c3ad6d
Remove playgroundCode from IApplicationState
ning-y May 15, 2018
fcf1c60
Fix type errors
ning-y May 15, 2018
4004d64
Re-disable console.logs (tslint)
ning-y May 15, 2018
1879083
Fix missing imports for react-ace mode, theme
ning-y May 15, 2018
1f5edb7
Add playground CSS
ning-y May 15, 2018
376ec46
Add JSDoc style comments for playground
ning-y May 15, 2018
eb37db7
Fix some tests
ning-y May 15, 2018
931a204
Fix semantics of mapStateToProps for ApplicationContainer
remo5000 May 16, 2018
b451e08
Do trivial formatting
remo5000 May 16, 2018
71d8c2d
Add interpreter toolchain as 'slang'
ning-y May 16, 2018
7a23838
Add react-saga and react types to yarn
remo5000 May 16, 2018
aeb3c2d
Add saga to middleware list
remo5000 May 16, 2018
f69381b
Segregate actionTypes from actions
remo5000 May 16, 2018
df3cde8
Fix reducer actionType import
remo5000 May 16, 2018
83f2064
Remove actionType import from action/index
remo5000 May 16, 2018
3c1705a
Fix fatal bug with defineVariable calls
ning-y May 16, 2018
31761b0
Fix missing imports
ning-y May 16, 2018
189d25b
Add tests for slang
ning-y May 16, 2018
e18f2ae
Remove unused type definitions
ning-y May 16, 2018
a36959c
Lint typescript files of slang
ning-y May 16, 2018
7f374bc
Add interruption actionType
remo5000 May 16, 2018
74df49f
Add sagas WIP
remo5000 May 16, 2018
aedffa3
Add more interpreter actions
remo5000 May 16, 2018
01c3514
Change to older version of saga
remo5000 May 16, 2018
9045d84
Merge remote-tracking branch 'origin/add-slang' into add-saga
remo5000 May 16, 2018
10662f7
Add notification file
remo5000 May 16, 2018
9b53194
Change es target to es2016
remo5000 May 16, 2018
56f9981
Revert "Remove unused type definitions"
remo5000 May 16, 2018
430bb4a
Fix some slang errors
remo5000 May 16, 2018
7ac707c
Make 16/05 code review changes
remo5000 May 16, 2018
b2a3d60
Fix test snapshot (name of onChange for ReactAce)
ning-y May 17, 2018
caf551b
Revert Playground as SFC, make Editor container
ning-y May 17, 2018
51ea83d
Make Playground stateless
remo5000 May 17, 2018
9758bb7
Add test and fix export type
remo5000 May 17, 2018
0438549
Fix type errors according to tslint
ning-y May 17, 2018
6c47695
Change object methods to use es6 shorthand
ning-y May 17, 2018
0349515
Fix more linting errors for interpreter.ts
ning-y May 17, 2018
99ad59e
Disable `no-empty` rule.
remo5000 May 17, 2018
54e085e
Merge branch 'add-saga' of https://github.com/source-academy/cadet-fr…
remo5000 May 17, 2018
04bdf0f
Add `max-classes-per-file` exception for interpreter files
remo5000 May 17, 2018
05f3243
Fix linting errors in parser, rules/braces...
ning-y May 17, 2018
9018abd
Fix tslint errors in `parser`
remo5000 May 17, 2018
22ec2ac
Format interpreter.ts
remo5000 May 17, 2018
3fbf3af
Fix tslint errors in rules/*
ning-y May 17, 2018
eba7c01
Merge branch 'add-saga' of github.com:source-academy/cadet-frontend i…
ning-y May 17, 2018
a8c50a6
Fix tslint errors for rttc.ts
ning-y May 17, 2018
766cb5b
Fix tslint errors for node.ts
ning-y May 17, 2018
67aba68
Fix tslint errors for types.ts
ning-y May 17, 2018
7a676ef
Fix stdlib/list, stdlib/misc and scheudler tslint
remo5000 May 17, 2018
0a6e87c
Fix `saga` not being run after store creation
remo5000 May 17, 2018
27a4edb
Merge branch 'scaffold-playground' into add-saga
ning-y May 17, 2018
e4f7743
Fix Editor test (tslint errors)
ning-y May 17, 2018
873a14b
Add properties context, output to IPlaygroundState
ning-y May 17, 2018
52210e5
Add button to call on handleEvalEditor
remo5000 May 17, 2018
4fa0b3c
Add mapDispatchToProps for EditorContainer
remo5000 May 17, 2018
cc4e238
Fix 'ace is undefined' error
remo5000 May 17, 2018
7044f52
Add Output SFC
ning-y May 17, 2018
2e01bea
Add output tests, did yarn format
ning-y May 17, 2018
b32ef00
Add 'run' button to EditorContainer
remo5000 May 17, 2018
3069c2e
Change Editor snapshot to include button
remo5000 May 17, 2018
8d9e033
Wire saga interpreter success to output SFC
ning-y May 17, 2018
c6580ce
Fix wrong file extension '.tsx' -> '.ts'
ning-y May 17, 2018
fbc658c
Move state definitions into their own file
ning-y May 17, 2018
50f04bf
Add type for interpreter outputs
remo5000 May 17, 2018
d4f587c
Merge branch 'add-saga-show-output' of https://github.com/source-acad…
remo5000 May 17, 2018
b2a2aa8
Fix #11, using bindActionCreators
remo5000 May 17, 2018
d108b1e
Merge branch 'precommit-push-lint-tests' into add-saga
ning-y May 17, 2018
e2fe096
Merge branch 'precommit-push-lint-tests' into add-saga
ning-y May 17, 2018
376dc2d
Add flexboxgrid dependency
ning-y May 18, 2018
520bc92
Line Editor and Output up side to side
ning-y May 18, 2018
6843ece
Refactor and modularise playground as IDE
ning-y May 18, 2018
45c2434
Change Output to Repl
remo5000 May 18, 2018
b3b9b72
Implement multiple Outputs in Repl (history)
ning-y May 18, 2018
aadef6e
Fix class playground not taking up all of parent
ning-y May 18, 2018
b315180
Make use of slang's toString to format values
ning-y May 18, 2018
3cd49a4
Make flexbox tags relative to current component
remo5000 May 18, 2018
875c342
Make IPlaygroundState properties readonly
remo5000 May 18, 2018
a42d5d5
Add ReplInput (not wired to saga)
ning-y May 18, 2018
bb0b1a1
Replace TextArea with AceEditor
ning-y May 18, 2018
88b2695
Move IDE buton to a separate Control component
remo5000 May 18, 2018
711a42e
Merge Adding of repl editor with Control
remo5000 May 18, 2018
1445095
Add property replValue to IPlaygroundState
ning-y May 18, 2018
e084759
Make repl read from state.playground.replValue
ning-y May 18, 2018
14f4bad
Add evalRepl
remo5000 May 18, 2018
1dee09a
Merge add-saga-persistent-repl into add-saga
remo5000 May 18, 2018
7c18755
Update Control snapshot with eval button
remo5000 May 18, 2018
e1b6fe4
Add action UPDATE_REPL_VALUE
ning-y May 18, 2018
c048a86
Implement persistent repl content across routes
ning-y May 18, 2018
8676f2b
Merge branch 'add-saga-persistent-repl' into add-saga
ning-y May 18, 2018
0e0e580
Did yarn format
ning-y May 18, 2018
37b7eb5
Add action clear repl
ning-y May 18, 2018
992d829
Make eval button clear the replValue
ning-y May 18, 2018
98096ef
Fix repl context resetting every eval
ning-y May 18, 2018
21a0677
Add keyboard shortcut for REPL
remo5000 May 18, 2018
ba4ea6e
Merge branch 'add-saga' of https://github.com/source-academy/cadet-fr…
remo5000 May 18, 2018
d5513c2
Fix formatting for repl shortcut
remo5000 May 18, 2018
93233ca
Errors are loosely represented as string 'error'
ning-y May 19, 2018
724e204
Fix yarn format git hooks passing for unformatted
ning-y May 19, 2018
97eb105
Add ParseError in slang
ning-y May 19, 2018
ac02274
Improve error messages to specify type of error
ning-y May 19, 2018
46dc5c0
Improve CSS for repl output
ning-y May 19, 2018
6f395c8
Fix many error messages not printing on new lines
ning-y May 19, 2018
007aca2
Fix editor not changing playground.context
ning-y May 19, 2018
b6c3f50
Change ParseError to a function, parseError
remo5000 May 20, 2018
54df1cf
Simplify REPL Output Component creation
remo5000 May 20, 2018
4447029
Rename playground css to ide
remo5000 May 20, 2018
f4236e6
Change Playground to IDE in ide.css
remo5000 May 20, 2018
7fb17a2
Change "ClEAR_REPL" to "CLEAR_REPL_INPUT"
remo5000 May 20, 2018
76fb316
Add button and actions to clear REPL output
remo5000 May 20, 2018
4bd3c44
Make the clear button wipe the REPL context
remo5000 May 20, 2018
722a68b
Merge branch 'ide-css' into add-saga
remo5000 May 20, 2018
0a2fe6a
Fix merge conflicts with master
ning-y May 21, 2018
f1574f6
Revert "Make clear button wipe the REPL context"
remo5000 May 21, 2018
baf3748
Remove duplicate EditorContainer
remo5000 May 21, 2018
25623a9
Fix button row in playground overflowing to right
ning-y May 21, 2018
2eb5eeb
Merge branch 'functioning-ide' of github.com:source-academy/cadet-fro…
ning-y May 21, 2018
d763f04
Make run button clearReplOutput, remove default
ning-y May 21, 2018
5113056
Output code typed in ReplInput as Output
ning-y May 21, 2018
440408a
Use array method concat, reorder definitions
ning-y May 21, 2018
9bef609
No verify commit, tests fails
ning-y May 21, 2018
5f97c2c
Fix failing tests
ning-y May 21, 2018
9438216
Make run button interrupt execution
ning-y May 21, 2018
57560b1
Make eval interrupt execution, remove notifs
ning-y May 21, 2018
7de5265
Fix display not working after a clear
ning-y May 21, 2018
8c80b7b
Fix Eval button crashing site when Output[] empty
ning-y May 21, 2018
37e07ab
Refactor display interactions with react/redux
ning-y May 22, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@
},
"husky": {
"hooks": {
"pre-commit": "yarn format && CI=true yarn test",
"pre-push": "yarn format && CI=true yarn test"
"pre-commit": "yarn format:ci && CI=true yarn test",
"pre-push": "yarn format:ci && CI=true yarn test"
}
},
"dependencies": {
"@blueprintjs/core": "^2.1.1",
"@types/acorn": "^4.0.3",
"astring": "^1.3.0",
"common-tags": "^1.7.2",
"flexboxgrid": "^6.3.1",
"normalize.css": "^8.0.0",
"react": "^16.3.1",
"react-ace": "^6.1.1",
Expand All @@ -37,13 +41,17 @@
"react-transition-group": "^2.3.1",
"redux": "^3.7.2",
"redux-mock-store": "^1.5.1",
"redux-saga": "^0.15.6",
"typesafe-actions": "^1.1.2",
"utility-types": "^2.0.0"
},
"devDependencies": {
"@types/classnames": "^2.2.3",
"@types/common-tags": "^1.4.0",
"@types/enzyme": "^3.1.9",
"@types/enzyme-adapter-react-16": "^1.0.2",
"@types/estree": "^0.0.39",
"@types/invariant": "^2.2.29",
"@types/jest": "^22.2.3",
"@types/node": "^9.6.5",
"@types/react": "^16.3.10",
Expand Down
22 changes: 22 additions & 0 deletions src/actions/actionTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Action as ReduxAction } from 'redux'

export interface IAction extends ReduxAction {
payload: any
}

/** Playground */
export const UPDATE_EDITOR_VALUE = 'UPDATE_EDITOR_VALUE'
export const UPDATE_REPL_VALUE = 'UPDATE_REPL_VALUE'
export const EVAL_EDITOR = 'EVAL_EDITOR'
export const EVAL_REPL = 'EVAL_REPL'
export const CLEAR_REPL_INPUT = 'CLEAR_REPL_INPUT'
export const CLEAR_REPL_OUTPUT = 'CLEAR_REPL_OUTPUT'
export const CLEAR_CONTEXT = 'CLEAR_CONTEXT'
export const SEND_REPL_INPUT_TO_OUTPUT = 'SEND_REPL_INPUT_TO_OUTPUT'

/** Interpreter */
export const HANDLE_CONSOLE_LOG = 'HANDLE_CONSOLE_LOG'
export const EVAL_INTERPRETER = 'EVAL_INTERPRETER'
export const EVAL_INTERPRETER_SUCCESS = 'EVAL_INTERPRETER_SUCCESS'
export const EVAL_INTERPRETER_ERROR = 'EVAL_INTERPRETER_ERROR'
export const INTERRUPT_EXECUTION = 'INTERRUPT_EXECUTION'
2 changes: 2 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './interpreter'
export * from './playground'
26 changes: 26 additions & 0 deletions src/actions/interpreter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { SourceError, Value } from '../slang/types'
import * as actionTypes from './actionTypes'

export const handleConsoleLog = (log: string) => ({
type: actionTypes.HANDLE_CONSOLE_LOG,
payload: log
})

export const evalInterpreter = (code: string) => ({
type: actionTypes.EVAL_INTERPRETER,
payload: code
})

export const evalInterpreterSuccess = (value: Value) => ({
type: actionTypes.EVAL_INTERPRETER_SUCCESS,
payload: { type: 'result', value }
})

export const evalInterpreterError = (errors: SourceError[]) => ({
type: actionTypes.EVAL_INTERPRETER_ERROR,
payload: { type: 'errors', errors }
})

export const handleInterruptExecution = () => ({
type: actionTypes.INTERRUPT_EXECUTION
})
62 changes: 38 additions & 24 deletions src/actions/playground.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
import { Action, ActionCreator } from 'redux'

/**
* The `type` attribute for an `Action` which updates the `IPlaygroundState`
* `editorValue`
*/
export const UPDATE_EDITOR_VALUE = 'UPDATE_EDITOR_VALUE'

/**
* Represents an `Action` which updates the `editorValue` of a
* `IPlaygroundState`
* @property type - Unique string identifier for this `Action`
* @property newEditorValue - The new string value for `editorValue`
*/
export interface IUpdateEditorValue extends Action {
payload: string
}

/**
* An `ActionCreator` returning an `IUpdateEditorValue` `Action`
* @param newEditorValue - The new string value for `editorValue`
*/
export const updateEditorValue: ActionCreator<IUpdateEditorValue> = (newEditorValue: string) => ({
type: UPDATE_EDITOR_VALUE,
import { ActionCreator } from 'redux'
import * as actionTypes from './actionTypes'

export const updateEditorValue: ActionCreator<actionTypes.IAction> = (newEditorValue: string) => ({
type: actionTypes.UPDATE_EDITOR_VALUE,
payload: newEditorValue
})

export const updateReplValue: ActionCreator<actionTypes.IAction> = (newReplValue: string) => ({
type: actionTypes.UPDATE_REPL_VALUE,
payload: newReplValue
})

export const sendReplInputToOutput: ActionCreator<actionTypes.IAction> = (newOutput: string) => ({
type: actionTypes.SEND_REPL_INPUT_TO_OUTPUT,
payload: {
type: 'code',
value: newOutput
}
})

export const evalEditor = () => ({
type: actionTypes.EVAL_EDITOR
})

export const evalRepl = () => ({
type: actionTypes.EVAL_REPL
})

export const clearReplInput = () => ({
type: actionTypes.CLEAR_REPL_INPUT
})

export const clearReplOutput = () => ({
type: actionTypes.CLEAR_REPL_OUTPUT
})

export const clearContext = () => ({
type: actionTypes.CLEAR_CONTEXT
})
50 changes: 50 additions & 0 deletions src/components/IDE/Control.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react'

import { Button, IconName, Intent } from '@blueprintjs/core'

/**
* @property handleEvalEditor - A callback function for evaluation
* of the editor's content, using `slang`
*/
export interface IControlProps {
handleEvalEditor: () => void
handleEvalRepl: () => void
handleClearReplOutput: () => void
}

class Control extends React.Component<IControlProps, {}> {
public render() {
const genericButton = (
label: string,
icon: IconName,
handleClick = () => {},
intent = Intent.NONE,
notMinimal = false
) => (
<Button
onClick={handleClick}
className={(notMinimal ? '' : 'pt-minimal') + ' col-xs-12'}
intent={intent}
icon={icon}
>
{label}
</Button>
)
const runButton = genericButton('Run', 'play', this.props.handleEvalEditor)
const evalButton = genericButton('Eval', 'play', this.props.handleEvalRepl)
const clearButton = genericButton('Clear', 'remove', this.props.handleClearReplOutput)
return (
<div className="row between-xs">
<div className="col-xs-2">{runButton}</div>
<div className="col-xs-4">
<div className="row">
<div className="col-xs-6">{evalButton}</div>
<div className="col-xs-6">{clearButton}</div>
</div>
</div>
</div>
)
}
}

export default Control
33 changes: 33 additions & 0 deletions src/components/IDE/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react'

import AceEditor from 'react-ace'

import 'brace/mode/javascript'
import 'brace/theme/terminal'

/**
* @property editorValue - The string content of the react-ace editor
* @property handleEditorChange - A callback function
* for the react-ace editor's `onChange`
*/
export interface IEditorProps {
editorValue: string
handleEditorChange: (newCode: string) => void
}

class Editor extends React.Component<IEditorProps, {}> {
public render() {
return (
<AceEditor
className="Editor col-xs-6"
mode="javascript"
theme="terminal"
value={this.props.editorValue}
onChange={this.props.handleEditorChange}
width="100%"
/>
)
}
}

export default Editor
59 changes: 59 additions & 0 deletions src/components/IDE/Repl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react'

import { Card } from '@blueprintjs/core'
import ReplInputContainer from '../../containers/IDE/ReplInputContainer'
import { InterpreterOutput } from '../../reducers/states'
import { parseError, toString } from '../../slang'

export interface IReplProps {
output: InterpreterOutput[]
}

export interface IOutputProps {
output: InterpreterOutput
}

const Repl: React.SFC<IReplProps> = props => {
const cards = props.output.map((slice, index) => <Output output={slice} key={index} />)
return (
<div className="Repl col-xs-6">
{cards}
<div className="row">
<ReplInputContainer />
</div>
</div>
)
}

export const Output: React.SFC<IOutputProps> = props => {
switch (props.output.type) {
case 'code':
return <Card>{props.output.value}</Card>
case 'running':
return <Card>{props.output.consoleLogs.join('\n')}</Card>
case 'result':
if (props.output.consoleLogs.length === 0) {
return <Card>{toString(props.output.value)}</Card>
} else {
return (
<Card>
{[props.output.consoleLogs.join('\n'), toString(props.output.value)].join('\n')}
</Card>
)
}
case 'errors':
if (props.output.consoleLogs.length === 0) {
return <Card>{parseError(props.output.errors)}</Card>
} else {
return (
<Card>
{[props.output.consoleLogs.join('\n'), parseError(props.output.errors)].join('\n')}
</Card>
)
}
default:
return <Card>''</Card>
}
}

export default Repl
41 changes: 41 additions & 0 deletions src/components/IDE/ReplInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as React from 'react'
import AceEditor from 'react-ace'

import 'brace/mode/javascript'
import 'brace/theme/terminal'

export interface IReplInputProps {
replValue: string
handleReplChange: (newCode: string) => void
handleReplEval: () => void
}

class ReplInput extends React.Component<IReplInputProps, {}> {
public render() {
return (
<AceEditor
className="col-xs-12"
mode="javascript"
theme="terminal"
height="1px"
value={this.props.replValue}
onChange={this.props.handleReplChange}
commands={[
{
name: 'evaluate',
bindKey: {
win: 'Shift-Enter',
mac: 'Shift-Enter'
},
exec: this.props.handleReplEval
}
]}
minLines={1}
maxLines={20}
showGutter={false}
/>
)
}
}

export default ReplInput
16 changes: 16 additions & 0 deletions src/components/IDE/__tests__/Control.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react'

import { shallow } from 'enzyme'

import Control, { IControlProps } from '../Control'

test('Control renders correctly', () => {
const props: IControlProps = {
handleEvalEditor: () => {},
handleEvalRepl: () => {},
handleClearReplOutput: () => {}
}
const app = <Control {...props} />
const tree = shallow(app)
expect(tree.debug()).toMatchSnapshot()
})
15 changes: 15 additions & 0 deletions src/components/IDE/__tests__/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as React from 'react'

import { shallow } from 'enzyme'

import Editor, { IEditorProps } from '../Editor'

test('Editor renders correctly', () => {
const props: IEditorProps = {
editorValue: '',
handleEditorChange: newCode => {}
}
const app = <Editor {...props} />
const tree = shallow(app)
expect(tree.debug()).toMatchSnapshot()
})
21 changes: 21 additions & 0 deletions src/components/IDE/__tests__/Repl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { shallow } from 'enzyme'
import * as React from 'react'

import { ResultOutput } from '../../../reducers/states'
import Repl, { Output } from '../Repl'

test('Repl renders correctly', () => {
const props = {
output: [{ type: 'result', value: 'abc', consoleLogs: [] } as ResultOutput]
}
const app = <Repl {...props} />
const tree = shallow(app)
expect(tree.debug()).toMatchSnapshot()
})

test("Output renders correctly for InterpreterOutput.type === 'result'", () => {
const props: ResultOutput = { type: 'result', value: 'def', consoleLogs: [] }
const app = <Output {...{ output: props }} />
const tree = shallow(app)
expect(tree.debug()).toMatchSnapshot()
})
Loading