From f7534d5570be20160177b161ca79ce755bd147d3 Mon Sep 17 00:00:00 2001
From: Zamil Majdy <z.majdy1996@gmail.com>
Date: Wed, 22 Mar 2017 20:13:03 +0700
Subject: [PATCH] [#140382397] #5 Heavy refactor js to follow coding convention

---
 .eslintrc                             |   7 +-
 assets/js/__test__/coba-test.js       |  25 ---
 assets/js/__test__/lib/logger-test.js |  25 +++
 assets/js/component.js                |   3 -
 assets/js/components/FormLogin.jsx    |  30 +++
 assets/js/components/ModalAlert.jsx   |  44 ++++
 assets/js/components/Pane.jsx         |  15 ++
 assets/js/components/SSOLogin.jsx     |  32 +++
 assets/js/components/Tabs.jsx         |  67 ++++++
 assets/js/components/TopMenu.jsx      |  24 ++
 assets/js/dashboard.jsx               |  49 ++--
 assets/js/index.js                    | 310 --------------------------
 assets/js/index.jsx                   | 137 ++++++++++++
 assets/js/lib/logger.jsx              |  54 ++---
 assets/js/lib/server.jsx              | 149 +++++++------
 assets/js/lib/storage.jsx             |  31 +--
 assets/js/login.jsx                   | 122 +++-------
 assets/js/root.js                     |  42 ----
 core/views/accounts.py                |   1 +
 npm-debug.log.1735884061              |   0
 package.json                          |   4 +-
 webpack.config.js                     |  34 +--
 22 files changed, 568 insertions(+), 637 deletions(-)
 delete mode 100755 assets/js/__test__/coba-test.js
 create mode 100644 assets/js/__test__/lib/logger-test.js
 delete mode 100755 assets/js/component.js
 create mode 100644 assets/js/components/FormLogin.jsx
 create mode 100644 assets/js/components/ModalAlert.jsx
 create mode 100644 assets/js/components/Pane.jsx
 create mode 100644 assets/js/components/SSOLogin.jsx
 create mode 100644 assets/js/components/Tabs.jsx
 create mode 100644 assets/js/components/TopMenu.jsx
 delete mode 100755 assets/js/index.js
 create mode 100644 assets/js/index.jsx
 delete mode 100755 assets/js/root.js
 create mode 100644 npm-debug.log.1735884061

diff --git a/.eslintrc b/.eslintrc
index 1ee944f9..c6197154 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -9,7 +9,12 @@
   },
   "rules": {
     "func-names": ["error", "never"],
-    "react/prefer-stateless-function": [0, { "ignorePureComponents": true }]
+    "react/prefer-stateless-function": [0, { "ignorePureComponents": true }],
+    "import/extensions": ["off", "never"],
+    "import/no-unresolved": 0,
+    "no-underscore-dangle" : 0,
+    "linebreak-style" : 0,
+    "no-extra-bind" : 0
   },
   "parser": "babel-eslint",
   "parserOptions": {
diff --git a/assets/js/__test__/coba-test.js b/assets/js/__test__/coba-test.js
deleted file mode 100755
index 432d9c75..00000000
--- a/assets/js/__test__/coba-test.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import ReactTestUtils from 'react-addons-test-utils' // ES6
-import expect from 'expect';
-import Root from '../root';
-
-describe('root', function () {
-    it('renders without problems', function () {
-        let root = ReactTestUtils.renderIntoDocument(<Root/>);
-        expect(root).toExist();
-    });
-
-    it('changes without problems', function () {
-        let root = ReactTestUtils.renderIntoDocument(<Root/>);
-
-        const inputNode = ReactDOM.findDOMNode(root.refs.input);
-
-        const newValue = 'some text';
-        inputNode.value = newValue;
-        ReactTestUtils.Simulate.change(inputNode);
-
-        const nameNode = ReactDOM.findDOMNode(root.refs.name);
-        expect(nameNode.textContent).toEqual(newValue);
-    });
-});
\ No newline at end of file
diff --git a/assets/js/__test__/lib/logger-test.js b/assets/js/__test__/lib/logger-test.js
new file mode 100644
index 00000000..ac3c13fc
--- /dev/null
+++ b/assets/js/__test__/lib/logger-test.js
@@ -0,0 +1,25 @@
+import expect from "expect";
+import Logger from "../../lib/logger";
+import {describe, beforeEach, it} from "mocha";
+
+describe('logger log', function () {
+    beforeEach(function() {
+        expect(Logger, 'log');
+        Logger.log("testing log");
+    });
+
+    it('Logger sent log properly', function () {
+        expect(console.log).toHaveBeenCalled();
+    });
+});
+
+describe('logger error', function () {
+    beforeEach(function() {
+        expect(Logger, 'error');
+        Logger.error("testing error");
+    });
+
+    it('Logger sent error properly', function () {
+        expect(console.log).toHaveBeenCalled();
+    });
+});
\ No newline at end of file
diff --git a/assets/js/component.js b/assets/js/component.js
deleted file mode 100755
index 8420d7a4..00000000
--- a/assets/js/component.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var component = TestUtils.renderIntoDocument(
-    <MyComponent />
-);
\ No newline at end of file
diff --git a/assets/js/components/FormLogin.jsx b/assets/js/components/FormLogin.jsx
new file mode 100644
index 00000000..a47a452d
--- /dev/null
+++ b/assets/js/components/FormLogin.jsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import { Form, Input, Button, Image } from 'semantic-ui-react';
+
+export default class FormLogin extends React.Component {
+  render = () => (
+    <div className="formLogin" >
+
+      <Image src="/assets/img/logo.png" size="small" verticalAlign="middle" /> <span>Company Login</span>
+
+      <Form>
+        <Form.Group widths="equal">
+          <Form.Field>
+            <label htmlFor="id"> Email </label>
+            <Input id="email" icon="user" iconPosition="left" placeholder="email" />
+          </Form.Field>
+        </Form.Group>
+
+        <Form.Group widths="equal">
+          <Form.Field>
+            <label htmlFor="password"> Password </label>
+            <Input id="password" icon="key" iconPosition="left" placeholder="password" />
+          </Form.Field>
+        </Form.Group>
+
+        <Button fluid color="blue">Login</Button>
+
+      </Form>
+    </div>
+  )
+}
diff --git a/assets/js/components/ModalAlert.jsx b/assets/js/components/ModalAlert.jsx
new file mode 100644
index 00000000..ac9d1703
--- /dev/null
+++ b/assets/js/components/ModalAlert.jsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import { Modal, Button, Icon } from 'semantic-ui-react';
+
+export default class ModalAlert extends React.Component {
+  static propTypes = {
+    onChangeValue: React.PropTypes.func.isRequired,
+    header: React.PropTypes.oneOfType([
+      React.PropTypes.node,
+      React.PropTypes.string,
+    ]).isRequired,
+    content: React.PropTypes.oneOfType([
+      React.PropTypes.node,
+      React.PropTypes.string,
+    ]).isRequired,
+  };
+
+  state = { open: false };
+
+  open = () => this.setState({ open: true });
+  close = () => this.setState({ open: false });
+
+  render() {
+    const { open } = this.state;
+
+    return (
+      <Modal
+        dimmer={false}
+        open={open}
+        onOpen={this.open}
+        onClose={this.close}
+        size="small"
+        trigger={<Button > Proceed <Icon name="right chevron" /></Button>}
+      >
+        <Modal.Header>{this.props.header}</Modal.Header>
+        <Modal.Content>
+          <p>{this.props.content}</p>
+        </Modal.Content>
+        <Modal.Actions>
+          <Button icon="check" content="All Done" onClick={this.props.onChangeValue} />
+        </Modal.Actions>
+      </Modal>
+    );
+  }
+}
\ No newline at end of file
diff --git a/assets/js/components/Pane.jsx b/assets/js/components/Pane.jsx
new file mode 100644
index 00000000..ae57febc
--- /dev/null
+++ b/assets/js/components/Pane.jsx
@@ -0,0 +1,15 @@
+import React from 'react';
+
+export default class Pane extends React.Component {
+  static displayName = 'Pane';
+
+  static propTypes = {
+    children: React.PropTypes.element.isRequired,
+  };
+
+  render = () => (
+    <div>
+      {this.props.children}
+    </div>
+    )
+}
diff --git a/assets/js/components/SSOLogin.jsx b/assets/js/components/SSOLogin.jsx
new file mode 100644
index 00000000..fd2b9438
--- /dev/null
+++ b/assets/js/components/SSOLogin.jsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { Form, Input, Button, Image } from 'semantic-ui-react';
+
+export default class SsoLogin extends React.Component {
+  render = () => (
+    <div className="formLogin" >
+
+      <Image src="/assets/img/UI.png" size="tiny" verticalAlign="middle" /> <span>  SSO Login</span>
+
+      <div className="input">
+        <Form>
+          <Form.Group widths="equal">
+            <Form.Field>
+              <label htmlFor="email">Email</label>
+              <Input id="email" icon="user" iconPosition="left" placeholder="email" />
+            </Form.Field>
+          </Form.Group>
+
+          <Form.Group widths="equal">
+            <Form.Field>
+              <label htmlFor="password">Password</label>
+              <Input id="password" icon="key" iconPosition="left" placeholder="password" />
+            </Form.Field>
+          </Form.Group>
+          <Button fluid color="blue" >Login</Button>
+
+        </Form>
+      </div>
+
+    </div>
+  )
+}
diff --git a/assets/js/components/Tabs.jsx b/assets/js/components/Tabs.jsx
new file mode 100644
index 00000000..a6317bc4
--- /dev/null
+++ b/assets/js/components/Tabs.jsx
@@ -0,0 +1,67 @@
+import React from 'react';
+
+export default class Tabs extends React.Component {
+  static displayName = 'Tabs';
+
+  static propTypes = {
+    selected: React.PropTypes.number.isRequired,
+    children: React.PropTypes.oneOfType([
+      React.PropTypes.array,
+      React.PropTypes.element,
+    ]).isRequired,
+  };
+
+  static defaultProps = () => ({
+    selected: 0,
+  });
+
+  constructor(props) {
+    super(props);
+    this.state = {
+      selected: this.props.selected,
+    };
+  }
+
+  shouldComponentUpdate = (nextProps, nextState) => (
+      this.props !== nextProps || this.state !== nextState
+  );
+
+  handleClick = (index, event) => {
+    event.preventDefault();
+    this.setState({
+      selected: index,
+    });
+  };
+
+  _renderTitles = () => {
+    function labels(child, index) {
+      const activeClass = (this.state.selected === index ? 'active' : '');
+      return (
+        <li key={index}>
+          <button className={activeClass} onClick={this.handleClick.bind(this, index)}>
+            {child.props.label}
+          </button>
+        </li>
+      );
+    }
+    return (
+      <ul className="tabs__labels">
+        {this.props.children.map(labels.bind(this))}
+      </ul>
+    );
+  };
+
+  _renderContent = () => (
+    <div className="tabs__content">
+      {this.props.children[this.state.selected]}
+    </div>
+    );
+
+
+  render = () => (
+    <div className="tabs">
+      {this._renderTitles()}
+      {this._renderContent()}
+    </div>
+    );
+}
diff --git a/assets/js/components/TopMenu.jsx b/assets/js/components/TopMenu.jsx
new file mode 100644
index 00000000..ed754c0b
--- /dev/null
+++ b/assets/js/components/TopMenu.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { Menu, Image } from 'semantic-ui-react';
+import { Link } from 'react-router';
+import Server from './../lib/server';
+
+export default class TopMenu extends React.Component {
+  state = { activeItem: 'home' };
+
+  render() {
+    return (
+      <Menu pointing secondary>
+        <Image as="a" size="small" src="/assets/img/logo.png" href="/" />
+        <Menu.Menu position="right">
+          <Menu.Item as={Link} to="/home" name="home" />
+          <Menu.Item as={Link} to="/profile" name="profil" />
+          {Server.isLoggedIn() ?
+            <Menu.Item as={Link} href="/api/api-auth/logout/?next=/" name="logout" /> :
+            <Menu.Item as={Link} to="/login" name="login" />
+                }
+        </Menu.Menu>
+      </Menu>
+    );
+  }
+}
diff --git a/assets/js/dashboard.jsx b/assets/js/dashboard.jsx
index 77790d3b..634fdefa 100755
--- a/assets/js/dashboard.jsx
+++ b/assets/js/dashboard.jsx
@@ -1,37 +1,18 @@
-import React, { Component } from "react";
-import {Menu, Segment, Image} from "semantic-ui-react";
-import {Link,Button, Header, Icon, Modal} from "react-router";
-import Server from "./lib/server";
+import React from 'react';
+import TopMenu from './components/TopMenu';
 
-export class TopMenu extends React.Component {
-  state = { activeItem: 'home' };
+export default class Dashboard extends React.Component {
+  static propTypes = {
+    children: React.PropTypes.oneOfType([
+      React.PropTypes.arrayOf(React.PropTypes.node),
+      React.PropTypes.node,
+    ]).isRequired,
+  };
 
-  render() {
-    return (
-        <Menu pointing secondary>
-          <Image as='a' size='small' src='/assets/img/logo.png' href='/'/>
-          <Menu.Menu position='right'>
-                <Menu.Item as={Link} to="/home" name='home' />
-                <Menu.Item as={Link} to="/profile" name='profil' />
-                {Server.isLoggedIn() ?
-                    <Menu.Item as={Link} href="/api/api-auth/logout/?next=/" name='logout' /> :
-                    <Menu.Item as={Link} to="/login" name='login' />
-                }
-          </Menu.Menu>
-        </Menu>
-    )
-  }
+  render = () => (
+    <div>
+      <TopMenu />
+      {this.props.children}
+    </div>
+  )
 }
-
-
-
-export default class Dashboard extends React.Component {
-    render = () => {
-        return (
-            <div>
-                <TopMenu/>
-                {this.props.children}
-            </div>
-        )
-    }
-}
\ No newline at end of file
diff --git a/assets/js/index.js b/assets/js/index.js
deleted file mode 100755
index a133f406..00000000
--- a/assets/js/index.js
+++ /dev/null
@@ -1,310 +0,0 @@
-import React from "react";
-import Dashboard from "./dashboard";
-import Login from './login';
-import ReactDOM from "react-dom";
-import {Router, Route, browserHistory} from "react-router";
-import {Segment, Modal, Button, Icon,Input,Menu,Image as ImageComponent, Item , Header,Grid, Divider,TextArea, Form } from "semantic-ui-react";
-
-import Server from "./lib/server"
-
-export const Profile = () => (
-    <Segment>
-        <img src='http://semantic-ui.com/images/wireframe/media-paragraph.png' />
-    </Segment>
-);
-
-class Greeting extends React.Component {
-    state = {
-        username : "unknown-user",
-        modalOpen : true
-    };
-
-    closeModal = () => {this.setState({modalOpen: false})};
-
-    componentWillMount() {
-        Server.get("/users/me/")
-            .then(results => {
-                results.username && this.setState({username : results.username});
-            }, error => {
-                // console.log(error);
-            });
-    }
-
-    render () {
-        return (
-         <Modal open={this.state.modalOpen} basic size='small' onClose={this.closeModal}>
-            <Modal.Content>
-              <h1 style={{textAlign : 'center'}}>
-                  <Icon loading name='like outline' size='large'/>
-                  Hi {this.state.username}
-                  <Icon loading name='like outline' size='large'/>
-              </h1>
-            </Modal.Content>
-            <Modal.Actions>
-              <Button color='green' inverted  onClick={this.closeModal} >
-                <Icon name='checkmark' /> Hi
-              </Button>
-            </Modal.Actions>
-          </Modal>
-        );
-    }
-}
-
-
-
-var Tabs = React.createClass({
-  displayName: 'Tabs',
-  propTypes: {
-    selected: React.PropTypes.number,
-    children: React.PropTypes.oneOfType([
-      React.PropTypes.array,
-      React.PropTypes.element
-    ]).isRequired
-  },
-  getDefaultProps: function () {
-    return {
-      selected: 0
-    };
-  },
-  getInitialState: function () {
-    return {
-      selected: this.props.selected
-    };
-  },
-  shouldComponentUpdate(nextProps, nextState) {
-    return this.props !== nextProps || this.state !== nextState;
-  },
-  handleClick: function (index, event) {
-    event.preventDefault();
-    this.setState({
-      selected: index
-    });
-  },
-  _renderTitles: function () {
-    function labels(child, index) {
-      var activeClass = (this.state.selected === index ? 'active' : '');
-      return (
-        <li key={index}>
-          <a href="#" 
-            className={activeClass}
-            onClick={this.handleClick.bind(this, index)}>
-            {child.props.label}
-          </a>
-        </li>
-      );
-    }
-    return (
-      <ul className="tabs__labels">
-        {this.props.children.map(labels.bind(this))}
-      </ul>
-    );
-  },
-  _renderContent: function () {
-    return (
-      <div className="tabs__content">
-        {this.props.children[this.state.selected]}
-      </div>
-    );
-  },
-  render: function () {
-    return (
-      <div className="tabs">
-        {this._renderTitles()}
-        {this._renderContent()}
-      </div>
-    );
-  }
-});
-
-var Pane = React.createClass({
-  displayName: 'Pane',
-  propTypes: {
-    label: React.PropTypes.string.isRequired,
-    children: React.PropTypes.element.isRequired
-  },
-  render: function () {
-    return (
-      <div>
-        {this.props.children}
-      </div>
-    );
-  }
-});
-
-export const Home = () => (
-      <div>
-            <Tabs selected={0}>
-              <Pane label="Semua Lowongan">
-                <ItemExampleFloated/>
-              </Pane>
-              <Pane label="Lamaran saya">
-                <div>This is my tab 2 contents!</div>
-              </Pane>
-            </Tabs>
-      </div>
-);
-
-export const App = () => (
-    <Router history={browserHistory}>
-        <Route path="/login" component={Login} />
-        <Route component={Dashboard}>
-            <Route path="/" component={Greeting} />
-            <Route path="profile" component={Profile} />
-            <Route path="home" component={Home} />
-            <Route path="users" component={Profile} />
-        </Route>
-    </Router>
-);
-
-
-
-const paragraph = <ImageComponent src='http://semantic-ui.com/images/wireframe/short-paragraph.png' />;
-
-export class ItemExampleFloated extends React.Component {
- 
-  render() {
-    return (
-         <Item.Group relaxed>
-    <Item>
-      
-            <Item.Image size='small' src='http://semantic-ui.com/images/wireframe/image.png' />
-            <Item.Content verticalAlign='middle'>
-              <Item.Header>Lowongan 1</Item.Header>
-              <Item.Description>{paragraph}</Item.Description>
-               <Item.Extra>
-              <div className="daftar">
-                <ModalExampleMultiple />
-              </div>
-            </Item.Extra>
-            </Item.Content>
-           
-      
-    </Item>
-
-    <Item>
-      
-            <Item.Image size='small' src='http://semantic-ui.com/images/wireframe/image.png' />
-            <Item.Content verticalAlign='middle'>
-              <Item.Header>Lowongan 2</Item.Header>
-              <Item.Description>{paragraph}</Item.Description>
-               <Item.Extra>
-              <div className="daftar">
-                <ModalExampleMultiple />
-              </div>
-            </Item.Extra>
-            </Item.Content>
-           
-      
-    </Item>
-
-     <Item>
-      
-            <Item.Image size='small' src='http://semantic-ui.com/images/wireframe/image.png' />
-            <Item.Content verticalAlign='middle'>
-              <Item.Header>Lowongan 3</Item.Header>
-              <Item.Description>{paragraph}</Item.Description>
-               <Item.Extra>
-              <div className="daftar">
-                <ModalExampleMultiple />
-              </div>
-            </Item.Extra>
-            </Item.Content>
-           
-      
-    </Item>
-
-    
-  </Item.Group>
-    )
-  }
-}
-
-export class NestedModal extends React.Component {
-  state = { open: false }
-
-  open = () => this.setState({ open: true })
-  close = () => this.setState({ open: false })
-
-  render() {
-    const { open } = this.state
-
-    return (
-      <Modal
-        dimmer={false}
-        open={open}
-        onOpen={this.open}
-        onClose={this.close}
-        size='small'
-        trigger={<Button > Proceed <Icon name='right chevron' /></Button>}
-      >
-        <Modal.Header>Pendaftaran</Modal.Header>
-        <Modal.Content>
-          <p>Terima kasih sudah mendaftar!</p>
-        </Modal.Content>
-        <Modal.Actions>
-          <Button icon='check' content='All Done'  onClick={this.props.onChangeValue} />
-        </Modal.Actions>
-      </Modal>
-    )
-  }
-}
-
-
-
-export class ModalExampleMultiple extends React.Component {
- 
-
-  state = { modalOpen: false }
-
-  handleOpen = (e) => this.setState({
-    modalOpen: true,
-  })
-
-  handleClose = (e) => this.setState({
-    modalOpen: false,
-  })
-
-  render() {
-    return (
-        <Modal
-         trigger={<Button onClick={this.handleOpen} >Daftar</Button>}
-         closeIcon='close' 
-         open={this.state.modalOpen}
-         onClose={this.handleClose}
-         >
-
-    <Modal.Header>Pendaftaran Lowongan</Modal.Header>
-    <Modal.Content image>
-      <div className='image'>
-        <Icon name='right arrow' />
-      </div>
-      <Modal.Description>
-        <Modal.Header> <h3> Deskripsi Lowongan </h3></Modal.Header>
-          {paragraph}
-
-        <div className='linkCV'>
-         <a> your latest CV </a>
-        </div>
-          
-        <div  className='coverLetter'>
-          <h5> Write your Cover Letter </h5>
-          <TextAreaExample />
-        </div>
-
-      </Modal.Description>
-    </Modal.Content>
-    <Modal.Actions>
-      <NestedModal onChangeValue={ this.handleClose } />
-    </Modal.Actions>
-  </Modal>
-    )
-  }
-}
-
-export const TextAreaExample = () => (
-  <Form>
-    <TextArea placeholder='Tell us more' />
-  </Form>
-);
-
-ReactDOM.render( <App />, document.getElementById('react-app'));
diff --git a/assets/js/index.jsx b/assets/js/index.jsx
new file mode 100644
index 00000000..8cce53ea
--- /dev/null
+++ b/assets/js/index.jsx
@@ -0,0 +1,137 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { Router, Route, browserHistory } from 'react-router';
+import { Segment, Modal, Button, Icon, Image as ImageComponent, Item, TextArea, Form } from 'semantic-ui-react';
+import Dashboard from './dashboard';
+import Login from './login';
+import Pane from './components/Pane';
+import Tabs from './components/Tabs';
+import ModalAlert from './components/ModalAlert';
+
+export const Profile = () => (
+  <Segment>
+    <img src="http://semantic-ui.com/images/wireframe/media-paragraph.png" alt="wire-frame" />
+  </Segment>
+);
+
+export const Home = () => (
+  <div>
+    <Tabs selected={0}>
+      <Pane label="Semua Lowongan">
+        <ItemExampleFloated />
+      </Pane>
+      <Pane label="Lamaran saya">
+        <div>This is my tab 2 contents!</div>
+      </Pane>
+    </Tabs>
+  </div>
+);
+
+export const App = () => (
+  <Router history={browserHistory}>
+    <Route path="/login" component={Login} />
+    <Route component={Dashboard}>
+      <Route path="/" component={Profile} />
+      <Route path="profile" component={Profile} />
+      <Route path="home" component={Home} />
+      <Route path="users" component={Profile} />
+    </Route>
+  </Router>
+);
+
+const paragraph = <ImageComponent src="http://semantic-ui.com/images/wireframe/short-paragraph.png" />;
+const imageWireFrame = <Item.Image size="small" src="http://semantic-ui.com/images/wireframe/image.png" />;
+
+export const ItemExampleFloated = () => (
+  <Item.Group relaxed>
+    <Item>
+      {imageWireFrame}
+      <Item.Content verticalAlign="middle">
+        <Item.Header>Lowongan 1</Item.Header>
+        <Item.Description>{paragraph}</Item.Description>
+        <Item.Extra>
+          <div className="daftar">
+            <ModalExampleMultiple />
+          </div>
+        </Item.Extra>
+      </Item.Content>
+    </Item>
+
+    <Item>
+      {imageWireFrame}
+      <Item.Content verticalAlign="middle">
+        <Item.Header>Lowongan 2</Item.Header>
+        <Item.Description>{paragraph}</Item.Description>
+        <Item.Extra>
+          <div className="daftar">
+            <ModalExampleMultiple />
+          </div>
+        </Item.Extra>
+      </Item.Content>
+    </Item>
+    <Item>
+      {imageWireFrame}
+      <Item.Content verticalAlign="middle">
+        <Item.Header>Lowongan 3</Item.Header>
+        <Item.Description>{paragraph}</Item.Description>
+        <Item.Extra>
+          <div className="daftar">
+            <ModalExampleMultiple />
+          </div>
+        </Item.Extra>
+      </Item.Content>
+    </Item>
+  </Item.Group>
+  );
+
+
+export class ModalExampleMultiple extends React.Component {
+
+  state = { modalOpen: false };
+
+  handleOpen = () => this.setState({
+    modalOpen: true,
+  });
+
+  handleClose = () => this.setState({
+    modalOpen: false,
+  });
+
+  render = () => (
+    <Modal
+      trigger={<Button onClick={this.handleOpen} >Daftar</Button>}
+      closeIcon="close"
+      open={this.state.modalOpen}
+      onClose={this.handleClose}
+    >
+
+      <Modal.Header>Pendaftaran Lowongan</Modal.Header>
+      <Modal.Content image>
+        <div className="image">
+          <Icon name="right arrow" />
+        </div>
+        <Modal.Description>
+          <Modal.Header> <h3> Deskripsi Lowongan </h3></Modal.Header>
+          {paragraph}
+
+          <div className="linkCV">
+            <a> your latest CV </a>
+          </div>
+
+          <div className="coverLetter">
+            <h5> Write your Cover Letter </h5>
+            <Form>
+              <TextArea placeholder="Tell us more" />
+            </Form>
+          </div>
+
+        </Modal.Description>
+      </Modal.Content>
+      <Modal.Actions>
+        <ModalAlert onChangeValue={this.handleClose} header="Pendaftaran" content="Terima kasih sudah mendaftar!" />
+      </Modal.Actions>
+    </Modal>
+    )
+}
+
+ReactDOM.render(<App />, document.getElementById('react-app'));
diff --git a/assets/js/lib/logger.jsx b/assets/js/lib/logger.jsx
index d55489a1..6118bd0f 100755
--- a/assets/js/lib/logger.jsx
+++ b/assets/js/lib/logger.jsx
@@ -1,42 +1,42 @@
 /* eslint-disable no-console */
 
-let DEV = (process.env.NODE_ENV !== "production");
+//  noinspection ES6ModulesDependencies,JSUnresolvedVariable
+const DEV = process.env.NODE_ENV !== 'production';
 
 export default class Logger {
-    static log(...args) {
-        if (DEV) {
-            console.log(...args);
-        }
+  static log(...args) {
+    if (DEV) {
+      console.log(...args);
     }
+  }
 
-    static warn(...args) {
-        if (DEV) {
-            console.warn(...args);
-        }
+  static warn(...args) {
+    if (DEV) {
+      console.warn(...args);
     }
+  }
 
-    static error(...args) {
-        if (DEV) {
-            console.error(...args);
-        }
+  static error(...args) {
+    if (DEV) {
+      console.error(...args);
     }
+  }
 
-    static serverError(error, callback) {
-        if (error.json) {
-            error.json().then(errorText => {
-                Logger.error(`Error ${errorText}`);
-                if (callback !== undefined) {
-                    callback(errorText);
-                }
-            });
-        }
-        else {
-            Logger.error(`Error ${error}`);
-            if (callback !== undefined) {
-                callback(error);
-            }
+  static serverError(error, callback) {
+    if (error.json) {
+      error.json().then((errorText) => {
+        Logger.error(`Error ${errorText}`);
+        if (callback !== undefined) {
+          callback(errorText);
         }
+      });
+    } else {
+      Logger.error(`Error ${error}`);
+      if (callback !== undefined) {
+        callback(error);
+      }
     }
+  }
 }
 
 global.Logger = Logger;
diff --git a/assets/js/lib/server.jsx b/assets/js/lib/server.jsx
index 437a8637..6796153c 100755
--- a/assets/js/lib/server.jsx
+++ b/assets/js/lib/server.jsx
@@ -1,88 +1,89 @@
-import Logger from "./logger";
-import Storage from "./storage";
+import Logger from './logger';
+import Storage from './storage';
 
 export default class Server {
-    static getCookie(name) {
-        let cookieValue = null;
-        if (document.cookie && document.cookie !== "") {
-            let cookies = document.cookie.split(";");
-            for (let i = 0; i < cookies.length; i++) {
-                let cookie = cookies[i].trim();
-                // Does this cookie string begin with the name we want?
-                if (cookie.substring(0, name.length + 1) === (name + "=")) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
+  static getCookie(name) {
+    let cookieValue = null;
+    if (document.cookie && document.cookie !== '') {
+      const cookies = document.cookie.split(';');
+      for (let i = 0; i < cookies.length; i += 1) {
+        const cookie = cookies[i].trim();
+        // Does this cookie string begin with the name we want?
+        if (cookie.substring(0, name.length + 1) === (`${name}`)) {
+          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
+          break;
         }
-        return cookieValue;
+      }
     }
+    return cookieValue;
+  }
 
-    static _request(path, method, data, useCache = false) {
+  static sendRequest(path, method, data, useCache = false) {
+    const url = `/api${path}`;
+    const csrftoken = this.getCookie('csrftoken');
+    const headers = {
+      'content-type': 'application/json',
+      Accept: 'application/json',
+      'X-CSRFToken': csrftoken,
+    };
+    const requestData = {
+      headers,
+      method,
+      body: data !== null ? JSON.stringify(data) : undefined,
+      credentials: 'same-origin',
+    };
 
-        let url = "/api" + path;
-        let csrftoken = this.getCookie("csrftoken");
-        let headers = {
-            "content-type": "application/json",
-            "Accept": "application/json",
-            "X-CSRFToken": csrftoken
-        };
-        let requestData = {
-            headers: headers,
-            method: method,
-            body: data !== null ? JSON.stringify(data) : undefined,
-            credentials: "same-origin",
-        };
-
-        let request = fetch(url, requestData);
-        let promise = request.then((response) => {
+    //  noinspection JSUnresolvedFunction
+    const request = fetch(url, requestData);
+    const promise = request.then((response) => {
             // Logger.log("[Server] Calling", url, response);
-            if (response.status < 200 || response.status > 399) {
-                throw response;
-            }
-            if (response.status === 204) {
-                return response;
-            }
-            return response.json();
-        });
+      if (response.status < 200 || response.status > 399) {
+        throw response;
+      }
+      if (response.status === 204) {
+        return response;
+      }
+      return response.json();
+    });
 
-        return useCache ? promise.then((response) => {
-            Logger.log("[Server] Response from", url, response);
-            Storage.set(path, response);
-            return response;
-        }) : promise.then((response) => {
-            Logger.log("[Server] Response from", url, response);
-            return response;
-        })
-    }
+    return useCache ? promise.then((response) => {
+      Logger.log('[Server] Response from', url, response);
+      Storage.set(path, response);
+      return response;
+    }) : promise.then((response) => {
+      Logger.log('[Server] Response from', url, response);
+      return response;
+    });
+  }
 
-    static get(path, useCache = true) {
-        return (useCache && Storage.get(path)) ?
-            Promise.resolve(Storage.get(path)) : this._request(path, "GET", null, useCache);
-    }
+  static get(path, useCache = true) {
+    return (useCache && Storage.get(path)) ?
+            Promise.resolve(Storage.get(path)) : this.sendRequest(path, 'GET', null, useCache);
+  }
 
-    static post(path, data) {
-        return this._request(path, "POST", data);
-    }
+  static post(path, data) {
+    return this.sendRequest(path, 'POST', data);
+  }
 
-    static patch(path, data) {
-        return this._request(path, "PATCH", data);
-    }
+  static patch(path, data) {
+    return this.sendRequest(path, 'PATCH', data);
+  }
 
-    static delete(path) {
-        return this._request(path, "DELETE", {});
-    }
+  //    noinspection ReservedWordAsName
+  static delete(path) {
+    return this.sendRequest(path, 'DELETE', {});
+  }
 
-    static request(url, method, payload, success, error) {
-        let request = new XMLHttpRequest();
-        request.open(method, url, true);
-        request.onload = success;
-        request.onerror = error;
-        request.setRequestHeader('Content-Type', 'text/plain');
-        return request.send(payload);
-    }
+  static request(url, method, payload, success, error) {
+    const request = new XMLHttpRequest();
+    request.open(method, url, true);
+    request.onload = success;
+    request.onerror = error;
+    request.setRequestHeader('Content-Type', 'text/plain');
+    return request.send(payload);
+  }
 
-    static isLoggedIn() {
-        return this.getCookie("sessionid");
-    }
-}
\ No newline at end of file
+  static isLoggedIn() {
+    return this.getCookie('sessionid');
+  }
+}
diff --git a/assets/js/lib/storage.jsx b/assets/js/lib/storage.jsx
index 79e2ca81..be269055 100644
--- a/assets/js/lib/storage.jsx
+++ b/assets/js/lib/storage.jsx
@@ -1,10 +1,12 @@
 /** Session Storage Polyfill */
+
+/* eslint-disable */
 var isStorageAvailable = function (storage) {
-  if (typeof storage == 'undefined') return false;
+  if (typeof storage === 'undefined') return false;
   try { // hack for safari incognito
-    storage.setItem("storage", "");
-    storage.getItem("storage");
-    storage.removeItem("storage");
+    storage.setItem('storage', '');
+    storage.getItem('storage');
+    storage.removeItem('storage');
     return true;
   }
   catch (err) {
@@ -108,17 +110,18 @@ if (!isStorageAvailable(window.localStorage)) window.localStorage = new Storage(
 if (!isStorageAvailable(window.sessionStorage)) window.sessionStorage = new Storage('session');
 
 })();
+/*eslint-enable */
 
 export default class Storage {
-    static get(key) {
-        return JSON.parse(sessionStorage.getItem(key))
-    }
+  static get(key) {
+    return JSON.parse(sessionStorage.getItem(key));
+  }
 
-    static set(key ,value) {
-        sessionStorage.setItem(key, JSON.stringify(value));
-    }
+  static set(key, value) {
+    sessionStorage.setItem(key, JSON.stringify(value));
+  }
 
-    static clear() {
-        sessionStorage.clear();
-    }
-}
\ No newline at end of file
+  static clear() {
+    sessionStorage.clear();
+  }
+}
diff --git a/assets/js/login.jsx b/assets/js/login.jsx
index 7a1016f2..1a8a1c4d 100644
--- a/assets/js/login.jsx
+++ b/assets/js/login.jsx
@@ -1,94 +1,38 @@
-import React from 'react'
-import { Form, Input, Icon, Button, Grid, Segment, Divider, Image,Card } from 'semantic-ui-react'
-
-
-export  class FormLogin extends React.Component {
-    render = () => {
-        return (
-          <div className="formLogin" >
-
-            <Image src='/assets/img/logo.png' size='small' verticalAlign='middle' /> <span>Company Login</span>
-
-               <Form>
-                  <Form.Group widths='equal'>
-                    <Form.Field>
-                      <label>Email</label>
-                      <Input icon='user' iconPosition='left' placeholder='email'/>
-                    </Form.Field>
-                  </Form.Group>
-
-                  <Form.Group widths='equal'>
-                    <Form.Field>
-                      <label>Password</label>
-                      <Input icon='key' iconPosition='left' placeholder='password' />
-                    </Form.Field>
-                  </Form.Group>
-
-                  <Button fluid color='blue'>Login</Button>
-
-              </Form>
-            </div>
-        )
-    }
-}
-
-
-export  class SsoLogin extends React.Component {
-    render = () => {
-        return (
-          <div className="formLogin" >
-
-            <Image src='/assets/img/UI.png' size='tiny' verticalAlign='middle' /> <span>  SSO Login</span>
-
-              <div className="input">
-                 <Form>
-                    <Form.Group widths='equal'>
-                      <Form.Field>
-                        <label>Email</label>
-                        <Input icon='user' iconPosition='left' placeholder='email'/>
-                      </Form.Field>
-                    </Form.Group>
-
-                    <Form.Group widths='equal'>
-                      <Form.Field>
-                        <label>Password</label>
-                        <Input icon='key' iconPosition='left' placeholder='password' />
-                      </Form.Field>
-                    </Form.Group>
-                    <Button fluid color='blue'  >Login</Button>
-                   
-                </Form>
-              </div>
-              
-            </div>
-        )
-    }
-}
-
-
+import React from 'react';
+import { Grid, Segment } from 'semantic-ui-react';
+import FormLogin from './components/FormLogin';
+import SSOLogin from './components/SSOLogin';
 
 export default class Login extends React.Component {
-    render = () => {
-        return (
-         <Grid columns={2} relaxed>
-          <Grid.Column>
-            <Segment basic>
-               <FormLogin/>
-                {this.props.children}
-            </Segment>
-          </Grid.Column>
-          
-           <Grid.Column>
-            <Segment basic>
-               <SsoLogin/>
-                {this.props.children}
-            </Segment>
-          </Grid.Column>
-                  
-          </Grid>
+
+  static defaultProps = {
+    children: null,
+  };
+
+  static propTypes = {
+    children: React.PropTypes.oneOfType([
+      React.PropTypes.arrayOf(React.PropTypes.node),
+      React.PropTypes.node,
+    ]),
+  };
+
+  render = () => (
+    <Grid columns={2} relaxed>
+      <Grid.Column>
+        <Segment basic>
+          <FormLogin />
+          {this.props.children}
+        </Segment>
+      </Grid.Column>
+
+      <Grid.Column>
+        <Segment basic>
+          <SSOLogin />
+          {this.props.children}
+        </Segment>
+      </Grid.Column>
+
+    </Grid>
         )
-    }
 }
 
-
-
diff --git a/assets/js/root.js b/assets/js/root.js
deleted file mode 100755
index fd9d6323..00000000
--- a/assets/js/root.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Created by M. Reza Qorib on 3/11/2017.
- */
-import React from 'react';
-
-class Root extends React.Component {
-    constructor(props) {
-        super(props);
-
-        this.state = {
-            name: ''
-        };
-
-        this.handleChange  = (e) => {
-            var newName = e.target.value;
-
-            this.setState({
-                name: newName
-            });
-        }
-    }
-
-    render() {
-        return (
-            <div>
-                <h1>Hello World!!</h1>
-
-                <p>
-                    Please input your name here:
-                    <input ref="input"
-                           onChange={this.handleChange}
-                           value={this.state.name}
-                    />
-                </p>
-
-                <p>Hello, <span ref="name">{this.state.name}</span> </p>
-            </div>
-        );
-    }
-}
-
-export default Root;
\ No newline at end of file
diff --git a/core/views/accounts.py b/core/views/accounts.py
index 07d8ef88..33bb4bb2 100644
--- a/core/views/accounts.py
+++ b/core/views/accounts.py
@@ -6,6 +6,7 @@ from rest_framework.response import Response
 from core.models.accounts import Student, Company, Supervisor
 from core.serializers.accounts import UserSerializer, StudentSerializer, CompanySerializer, SupervisorSerializer
 
+
 class UserViewSet(viewsets.ModelViewSet):
     queryset = User.objects.all()
     serializer_class = UserSerializer
diff --git a/npm-debug.log.1735884061 b/npm-debug.log.1735884061
new file mode 100644
index 00000000..e69de29b
diff --git a/package.json b/package.json
index 19b005b5..60cbd095 100755
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
   "license": "ISC",
   "devDependencies": {
     "babel": "^6.5.2",
+    "babel-eslint": "^7.2.0",
     "babel-loader": "^6.2.5",
     "babel-preset-es2015": "^6.22.0",
     "babel-preset-stage-1": "^6.16.0",
@@ -23,6 +24,7 @@
     "eslint-plugin-import": "^2.2.0",
     "eslint-plugin-jsx-a11y": "^4.0.0",
     "eslint-plugin-react": "^6.10.3",
+    "eslint-watch": "^3.0.1",
     "expect": "^1.20.2",
     "expect.js": "^0.3.1",
     "istanbul-instrumenter-loader": "^2.0.0",
@@ -34,7 +36,6 @@
     "karma-sourcemap-loader": "^0.3.7",
     "karma-webpack": "^2.0.2",
     "mocha": "^3.2.0",
-    "react": "^15.4.0",
     "react-addons-test-utils": "^15.4.2",
     "react-hot-loader": "^3.0.0-beta.5",
     "react-test-utils": "0.0.1",
@@ -43,6 +44,7 @@
     "webpack-dev-server": "^1.16.2"
   },
   "dependencies": {
+    "react": "^15.4.0",
     "axios": "^0.14.0",
     "babel-core": "^6.17.0",
     "babel-preset-react": "^6.16.0",
diff --git a/webpack.config.js b/webpack.config.js
index b07c2c85..cb176d4a 100755
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,6 +1,6 @@
-var path = require("path")
-var webpack = require('webpack')
-var BundleTracker = require('webpack-bundle-tracker')
+const path = require('path');
+const webpack = require('webpack');
+const BundleTracker = require('webpack-bundle-tracker');
 
 module.exports = {
   context: __dirname,
@@ -8,34 +8,34 @@ module.exports = {
   entry: './assets/js/index', // entry point of our app. assets/js/index.js should require other js modules and dependencies it needs
 
   output: {
-      path: path.resolve('./assets/bundles/'),
-      filename: "[name]-[hash].js",
+    path: path.resolve('./assets/bundles/'),
+    filename: '[name]-[hash].js',
   },
 
   plugins: [
     new webpack.HotModuleReplacementPlugin(),
-    new BundleTracker({filename: './webpack-stats.json'})
+    new BundleTracker({ filename: './webpack-stats.json' }),
   ],
 
   module: {
     loaders: [
-      { test: /\.jsx?$/, 
-        exclude: /node_modules/, 
+      { test: /\.jsx?$/,
+        exclude: /node_modules/,
         loader: 'babel-loader', // to transform JSX into JS
         query:
         {
-          presets:['react', 'es2015', 'stage-1']
-        }
-      }
+          presets: ['react', 'es2015', 'stage-1'],
+        },
+      },
     ],
-    postLoaders: [ { //delays coverage til after tests are run, fixing transpiled source coverage error
-            test: /\.js$/,
-            exclude: /(test|node_modules|bower_components)\//,
-            loader: 'istanbul-instrumenter' } ]
+    postLoaders: [{
+      test: /\.js$/,
+      exclude: /(test|node_modules|bower_components)\//,
+      loader: 'istanbul-instrumenter' }],
   },
 
   resolve: {
     modulesDirectories: ['node_modules', 'bower_components'],
-    extensions: ['', '.js', '.jsx']
+    extensions: ['', '.js', '.jsx'],
   },
-}
+};
-- 
GitLab