diff --git a/gates/webapp.js b/gates/webapp.js
index 6d07560..d275eac 100644
--- a/gates/webapp.js
+++ b/gates/webapp.js
@@ -20,9 +20,9 @@ expressApp.use(
expressApp.use(cors());
expressApp.options(cors());
expressApp.use(express.static(publicPath));
-expressApp.get('*',(req,res) => {
- res.sendFile(path.join(publicPath, 'index.html'))
-});
+// expressApp.get('*',(req,res) => {
+// res.sendFile(path.join(publicPath, 'index.html'))
+// });
expressApp.use(bodyParser.json());
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..ab4ff72
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "allowJs": true
+ }
+}
\ No newline at end of file
diff --git a/ui/config-overrides.js b/ui/config-overrides.js
new file mode 100644
index 0000000..35c227e
--- /dev/null
+++ b/ui/config-overrides.js
@@ -0,0 +1,5 @@
+/** @format */
+
+const {override, addDecoratorsLegacy, disableEsLint} = require('customize-cra');
+
+module.exports = override(addDecoratorsLegacy(), disableEsLint());
diff --git a/ui/package-lock.json b/ui/package-lock.json
index c1cd622..5516b96 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -275,6 +275,18 @@
"@babel/plugin-syntax-class-properties": "^7.0.0"
}
},
+ "@babel/plugin-proposal-decorators": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.1.2.tgz",
+ "integrity": "sha512-YooynBO6PmBgHvAd0fl5e5Tq/a0pEC6RqF62ouafme8FzdIVH41Mz/u1dn8fFVm4jzEJ+g/MsOxouwybJPuP8Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.0.0",
+ "@babel/plugin-syntax-decorators": "^7.1.0"
+ }
+ },
"@babel/plugin-proposal-json-strings": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz",
@@ -328,6 +340,15 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
+ "@babel/plugin-syntax-decorators": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.1.0.tgz",
+ "integrity": "sha512-uQvRSbgQ0nQg3jsmIixXXDCgSpkBolJ9X7NYThMKCcjvE8dN2uWJUzTUNNAeuKOjARTd+wUQV0ztXpgunZYKzQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
"@babel/plugin-syntax-dynamic-import": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0.tgz",
@@ -3394,6 +3415,16 @@
"cssom": "0.3.x"
}
},
+ "customize-cra": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-0.1.1.tgz",
+ "integrity": "sha512-Te22FctWJbpkxZDkGxonvjwAO5kvE0dyHik39IrJYk3tTL9wE+y3bo0uhYhh3MS03Soap76fZ5AEs8mkn85WOg==",
+ "dev": true,
+ "requires": {
+ "lodash.curry": "^4.1.1",
+ "lodash.flow": "^3.5.0"
+ }
+ },
"cyclist": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
@@ -7714,11 +7745,23 @@
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
+ "lodash.curry": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
+ "integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=",
+ "dev": true
+ },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
+ "lodash.flow": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
+ "integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -11466,6 +11509,35 @@
"whatwg-fetch": "3.0.0"
}
},
+ "react-app-rewired": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-1.6.2.tgz",
+ "integrity": "sha512-TxbP1W9jPPTmj0YJeFNgcJc6IMg7sv845aHUIUvVQtXdA8IWzOZairk3Bth6GHbxoF2QitbvUlM7/NAH4VmmJg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.1.0",
+ "dotenv": "^4.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "dotenv": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
+ "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=",
+ "dev": true
+ }
+ }
+ },
"react-bootstrap": {
"version": "1.0.0-beta.1",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.0.0-beta.1.tgz",
diff --git a/ui/package.json b/ui/package.json
index a2bb445..437078c 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -1,5 +1,5 @@
{
- "name": "client",
+ "name": "chaos_monkey",
"version": "1.0.0",
"private": true,
"dependencies": {
@@ -16,10 +16,10 @@
"socket.io-client": "^2.1.1"
},
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
- "eject": "react-scripts eject"
+ "start": "react-app-rewired start",
+ "build": "react-app-rewired build",
+ "test": "react-app-rewired test",
+ "eject": "react-app-rewired eject"
},
"eslintConfig": {
"extends": "react-app"
@@ -29,5 +29,10 @@
"not dead",
"not ie <= 11",
"not op_mini all"
- ]
+ ],
+ "devDependencies": {
+ "@babel/plugin-proposal-decorators": "^7.1.2",
+ "customize-cra": "^0.1.1",
+ "react-app-rewired": "^1.6.2"
+ }
}
diff --git a/ui/src/App.css b/ui/src/App.css
index eddf720..d2fb163 100644
--- a/ui/src/App.css
+++ b/ui/src/App.css
@@ -1,4 +1,8 @@
.app_logo {
height: 30px;
margin:0 8px;
+}
+
+.button_fixed {
+ position: fixed;
}
\ No newline at end of file
diff --git a/ui/src/components/CreatePrank/CreatePlankList.jsx b/ui/src/components/CreatePrank/CreatePlankList.jsx
index d016b74..18dc261 100644
--- a/ui/src/components/CreatePrank/CreatePlankList.jsx
+++ b/ui/src/components/CreatePrank/CreatePlankList.jsx
@@ -1,53 +1,37 @@
/** @format */
-import React, {Fragment} from 'react';
+import React from 'react';
+import {observer} from 'mobx-react';
// Styles
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
import ListGroup from 'react-bootstrap/lib/ListGroup';
-import Dropdown from 'react-bootstrap/lib/Dropdown';
-import DropdownButton from 'react-bootstrap/lib/DropdownButton';
-const CreatePlankList = ({items, listName, howLong}) => {
+const CreatePlankList = observer(({items, listName, onClick}) => {
return (
-
-
-
- {listName}
-
-
-
- {items.map(item => (
-
- {item}
-
- ))}
-
- More...
-
-
-
-
- {howLong && (
-
- New Line
-
-
+
+ {listName}
+
+
+
+ {items.map((item, idx) => (
+ onClick(item)}
>
- 5 sec
- 10 sec
- 30 sec
- 1 min
-
-
-
- )}
-
+ {item.name}
+
+ ))}
+
+ More...
+
+
+
+
);
-};
+});
export default CreatePlankList;
diff --git a/ui/src/components/CreatePrank/CreatePrank.jsx b/ui/src/components/CreatePrank/CreatePrank.jsx
index e42593b..50d7d65 100644
--- a/ui/src/components/CreatePrank/CreatePrank.jsx
+++ b/ui/src/components/CreatePrank/CreatePrank.jsx
@@ -1,47 +1,70 @@
/** @format */
import React, {Component} from 'react';
+import {inject, observer} from 'mobx-react';
import CreatePlankList from './CreatePlankList';
+import DurationDropdown from './DurationDropdown';
// Styles
-// import Button from 'react-bootstrap/lib/Button';
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
import Button from 'react-bootstrap/lib/Button';
+@inject('store')
+@observer
class CreatePrank extends Component {
state = {
- selectedItem: '',
- items: [
- 'Random with surprises',
- 'Exhausted hardware',
- 'Error handling benchmark',
- 'Slow and comprhensive',
+ selectedPrank: '',
+ pranks: [
+ {name: 'Random with surprises'},
+ {name: 'Exhausted hardware'},
+ {name: 'Error handling benchmark'},
+ {name: 'Slow and comprhensive'},
],
};
+ componentDidMount() {
+ this.props.store.getSinglePranksList();
+ }
+
+ createPrank = prank => {
+ this.props.store.addPrank(prank);
+ };
render() {
+ const {singlePranks} = this.props.store;
+ console.log('Selected Prank', this.state.selectedPrank.name);
return (
-
+
Create Plank
+
- OR
-
-
+
+ OR
+
+
+
-
+ this.setState({selectedPrank: prank})}
+ />
-
+
diff --git a/ui/src/components/CreatePrank/DurationDropdown.jsx b/ui/src/components/CreatePrank/DurationDropdown.jsx
new file mode 100644
index 0000000..4a29127
--- /dev/null
+++ b/ui/src/components/CreatePrank/DurationDropdown.jsx
@@ -0,0 +1,31 @@
+/** @format */
+
+import React from 'react';
+
+// Styles
+import Col from 'react-bootstrap/lib/Col';
+import Row from 'react-bootstrap/lib/Row';
+import Dropdown from 'react-bootstrap/lib/Dropdown';
+import DropdownButton from 'react-bootstrap/lib/DropdownButton';
+
+const DurationDropdown = () => {
+ return (
+
+ How long
+
+
+ 5 sec
+ 10 sec
+ 30 sec
+ 1 min
+
+
+
+ );
+};
+
+export default DurationDropdown;
diff --git a/ui/src/components/Dashboard.jsx b/ui/src/components/Dashboard.jsx
index 2f191f2..1d3988d 100644
--- a/ui/src/components/Dashboard.jsx
+++ b/ui/src/components/Dashboard.jsx
@@ -9,11 +9,11 @@ import Menu from './Menu';
import Container from 'react-bootstrap/lib/Container';
import Row from 'react-bootstrap/lib/Row';
-const Dashboard = ({children, ...rest}) => {
+const Dashboard = ({children, name}) => {
return (
-
+
diff --git a/ui/src/components/Header.jsx b/ui/src/components/Header.jsx
index 3751228..da2cda5 100644
--- a/ui/src/components/Header.jsx
+++ b/ui/src/components/Header.jsx
@@ -7,13 +7,14 @@ import Breadcrumb from 'react-bootstrap/lib/Breadcrumb';
import Col from 'react-bootstrap/lib/Col';
import monkeyLogo from '../assets/chaos-monkey.png';
-const Header = () => {
+const Header = props => {
+ console.log(props);
return (
-
+
Chaos control
- Create prank
+ {props.name}
);
diff --git a/ui/src/components/PranksLog/PranksLog.jsx b/ui/src/components/PranksLog/PranksLog.jsx
index 07559c3..05eb7c3 100644
--- a/ui/src/components/PranksLog/PranksLog.jsx
+++ b/ui/src/components/PranksLog/PranksLog.jsx
@@ -1,7 +1,7 @@
/** @format */
import React, {Component} from 'react';
-import io from 'socket.io-client';
+import {inject, observer} from 'mobx-react';
import PranksLogList from './PranksLogList';
import PrankScore from './PrankScore';
@@ -9,37 +9,20 @@ import PrankScore from './PrankScore';
// Styles
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
-import Button from 'react-bootstrap/lib/Button';
-
-const socket = io('http://localhost:8081');
+@inject('store')
+@observer
class PranksLog extends Component {
- state = {
- items: [],
- };
-
componentDidMount() {
- socket.connect();
- console.log('Socket Connected', 'Will auto DC in 30sec');
- socket.on('new-prank-activity', data => {
- if (data) {
- this.setState({items: [...this.state.items, data]});
- } else {
- console.log(`A new prank just ran ${JSON.stringify(data)}`);
- }
- });
- setTimeout(() => {
- socket.disconnect();
- console.log('Socket AUTO Disconnected');
- }, 30000);
+ this.props.store.getPranksLog();
+ }
+
+ componentWillUnmount() {
+ this.props.store.disconnect();
}
- dc = () => {
- socket.disconnect();
- console.log('Socket Disconnected !');
- };
render() {
- const {items} = this.state;
+ const {pranksLog, crazyScore} = this.props.store;
return (
@@ -47,17 +30,9 @@ class PranksLog extends Component {
Pranks log
-
-
-
-
-
-
- after loading too much items press the RED button
-
+
+
);
diff --git a/ui/src/components/PranksLog/PranksLogList.jsx b/ui/src/components/PranksLog/PranksLogList.jsx
index a39f263..2b8c7bd 100644
--- a/ui/src/components/PranksLog/PranksLogList.jsx
+++ b/ui/src/components/PranksLog/PranksLogList.jsx
@@ -2,6 +2,7 @@
import React, {Fragment} from 'react';
import moment from 'moment';
+import {observer} from 'mobx-react';
// Styles
import Badge from 'react-bootstrap/lib/Badge';
@@ -9,7 +10,7 @@ import Card from 'react-bootstrap/lib/Card';
import Col from 'react-bootstrap/lib/Col';
import Row from 'react-bootstrap/lib/Row';
-const PranksLogList = ({items}) => {
+const PranksLogList = observer(({items}) => {
return (
{items &&
@@ -48,6 +49,6 @@ const PranksLogList = ({items}) => {
)}
);
-};
+});
export default PranksLogList;
diff --git a/ui/src/index.js b/ui/src/index.js
index 1317768..2a30a4a 100644
--- a/ui/src/index.js
+++ b/ui/src/index.js
@@ -2,12 +2,20 @@
import React from 'react';
import ReactDOM from 'react-dom';
+import {Provider} from 'mobx-react';
+
+import store from './stores/prankStore';
import 'bootstrap/dist/css/bootstrap.min.css';
import App from './App.jsx';
import * as serviceWorker from './serviceWorker';
import './index.css';
-ReactDOM.render(, document.getElementById('root'));
+ReactDOM.render(
+
+
+ ,
+ document.getElementById('root')
+);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
diff --git a/ui/src/router/AppRouter.jsx b/ui/src/router/AppRouter.jsx
index 7563b88..42f7233 100644
--- a/ui/src/router/AppRouter.jsx
+++ b/ui/src/router/AppRouter.jsx
@@ -10,11 +10,15 @@ import RouteContainer from './RouteContainer';
export const history = createHistory();
-const AppRouter = () => (
+const AppRouter = props => (
-
-
+
+
);
diff --git a/ui/src/router/RouteContainer.jsx b/ui/src/router/RouteContainer.jsx
index fb796a2..d5894cc 100644
--- a/ui/src/router/RouteContainer.jsx
+++ b/ui/src/router/RouteContainer.jsx
@@ -9,11 +9,11 @@ const RouteContainer = ({component: Component, ...rest}) => (
(
-
+
)}
/>
);
-export default RouteContainer;
\ No newline at end of file
+export default RouteContainer;
diff --git a/ui/src/stores/prankStore.js b/ui/src/stores/prankStore.js
new file mode 100644
index 0000000..30ff392
--- /dev/null
+++ b/ui/src/stores/prankStore.js
@@ -0,0 +1,67 @@
+/** @format */
+
+import {action, observable, computed} from 'mobx';
+import axios from 'axios';
+import io from 'socket.io-client';
+
+const socket = io('http://localhost:8081');
+
+class PrankStore {
+ @observable
+ singlePranks = [];
+ @observable
+ pranksLog = [];
+
+ @computed
+ get crazyScore() {
+ let score = 0;
+ score =
+ score +
+ Math.floor(
+ this.pranksLog.length * Math.floor(Math.random() * Math.floor(10))
+ );
+ return score;
+ }
+ @action.bound
+ async getSinglePranksList() {
+ try {
+ const res = await axios.get('http://localhost:8081/chaos/pranks-pool');
+ this.singlePranks = res.data;
+ console.log(res.data);
+ } catch (e) {
+ console.log('Error getting pranks list', e);
+ }
+ }
+
+ @action.bound
+ getPranksLog() {
+ socket.connect();
+ console.log('Socket Connected');
+ socket.on('new-prank-activity', data => {
+ if (data) {
+ console.log(data);
+ this.pranksLog.push(data);
+ } else {
+ console.log(`A new prank just ran ${JSON.stringify(data)}`);
+ }
+ });
+ }
+
+ @action.bound
+ disconnect() {
+ socket.disconnect();
+ console.log('Socket Disconnected');
+ }
+ @action.bound
+ async addPrank(prank) {
+ try {
+ await axios.post('http://localhost:8081/chaos/pranks-activity', prank);
+ console.log('Prank Added Successfully');
+ } catch (e) {
+ console.log('Error Adding Prank', e);
+ }
+ }
+}
+
+const store = new PrankStore();
+export default store;
diff --git a/ui/src/stores/pranksStore.jsx b/ui/src/stores/pranksStore.jsx
deleted file mode 100644
index e69de29..0000000