Skip to content

Commit

Permalink
done
Browse files Browse the repository at this point in the history
  • Loading branch information
lkatartn committed Feb 9, 2017
1 parent 3a6d0ed commit de0b7f7
Show file tree
Hide file tree
Showing 15 changed files with 284 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/db.js → db.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.export = {
module.exports = {
users: [
{
id: 1,
Expand Down
16 changes: 13 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const app = require('express')();
const WebSocket = require('ws');
const db = require('./src/db');
const db = require('./db');
const wss = new WebSocket.Server({ port: 2322 });


Expand All @@ -15,8 +15,18 @@ wss.on('connection', function connection(ws) {
});

app.get('/users', function(req, res) {
// res.send('[{"id": 1, "name": "BOB"}]')
res.json([{id: 1, name: "BOB"}])
setTimeout(
() => res.json(db.users),
500
)
})
app.get('/user/:userId', function(req, res) {
const id = req.params.userId;
const userData = db.extendedData[id];
setTimeout(
() => res.json(userData),
id * 750
)
})

app.listen(2323);
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
"axios": "^0.15.3",
"babel-core": "^6.22.1",
"babel-loader": "^6.2.10",
"babel-preset-es2016": "^6.22.0",
"babel-preset-react": "^6.22.0",
"express": "^4.14.1",
"jsx-loader": "^0.13.2",
"react": "^15.3.2",
"react-dom": "^15.4.2",
"react-hot-loader": "^3.0.0-beta.6",
Expand All @@ -23,11 +20,9 @@
"babel-core": "^6.17.0",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.22.0",
"babel-preset-es2015": "^6.16.0",
"babel-preset-es2016": "^6.16.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.22.0",
"babel-preset-stage-2": "^6.22.0",
"css-loader": "^0.25.0",
"jsx-loader": "^0.13.2",
"node-sass": "^3.10.1",
Expand All @@ -39,7 +34,8 @@
"webpack-dev-server": "^1.16.1"
},
"scripts": {
"start": "./node_modules/webpack-dev-server/bin/webpack-dev-server.js --hot --progress --colors --port 8888 --content-base build/"
"server": "node index",
"start": "webpack-dev-server --hot --progress --colors --port 4242 --content-base build/"
},
"author": "",
"license": "ISC"
Expand Down
13 changes: 11 additions & 2 deletions src/actions.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
export default {
INIT: 'INIT',

USER_SELECTED: 'USER_SELECTED',
USERS_FETCH_ING: 'USERS_FETCH_ING',
USERS_FETCH_SUCCESS: 'USERS_FETCH_SUCCESS',
USERS_FETCH_FAIL: 'USERS_FETCH_FAIL',

CANCEL_INFO_FETCH: 'CANCEL_INFO_FETCH',

USER_INFO_ING: 'USER_INFO_ING',
USER_INFO_SUCCESS: 'USER_INFO_SUCCESS',
USER_INFO_FAIL: 'USER_INFO_FAIL',

RCV_MSG: 'RCV_MSG',
SND_MSG: 'SND_MSG',
WS_OPEN_PENDING: 'WS_OPEN_PENDING',
WS_OPEN_SUCCESS: 'WS_OPEN_SUCCESS',
WS_OPEN_FAIL: 'WS_OPEN_FAIL',
WS_CLOSING: 'WS_CLOSING',
WS_CLOSED: 'WS_CLOSED',
WS_MSG_RECEIVED: 'WS_MSG_RECEIVED',
WS_MSG_SEND: 'WS_MSG_SEND',
}
12 changes: 8 additions & 4 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { createStore, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducers/index'
import Root from './root.jsx';
import rootSaga from './sagas';
import wsSaga from './wsSaga';
import './style.scss';

const sagaMiddleware = createSagaMiddleware();
Expand All @@ -23,9 +24,12 @@ const store = createStore(
),
),
);
sagaMiddleware.run(rootSaga);


sagaMiddleware.run(function* (){
yield [
rootSaga(),
// wsSaga(),
]
});

ReactDOM.render(
(<Provider store={store}>
Expand Down
21 changes: 17 additions & 4 deletions src/components.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@ import React from 'react';

const User = ({ user, onClick, isSelected }) => (
<div
classname={`user ${(isSelected? 'selected' : 'null')}`}
className={`user ${(isSelected? 'selected' : '')}`}
onClick={() => onClick(user)}
>
{user.name}
</div>
);

export const Table = ({ users, onClickUser }) => (<div classname="users">
{users.map((user) => <div classname="user" onClick={onClickUser}></div>)}
export const UserData = ({ userName, age, loading }) => (
<div className={`userdata ${loading ? 'loading' : ''}`}>
<div className="name">Full Name: {userName}</div>
<div className="age">Age: <b>{age}</b></div>
</div>
);
export const Table = ({ users, onClickUser, selected }) => (
<div className="users">
{users.map((user) =>
<User
key={user.id}
onClick={onClickUser}
user={user}
isSelected={selected.id === user.id}
/>
)}
</div>);
14 changes: 11 additions & 3 deletions src/containers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@ import { connect } from 'react-redux';
import actions from './actions';
import {
Table,
} from './components';
UserData,
} from './components.jsx';

export const TableConnected = connect(
(state) => ({
users: state.users.data,
selected: state.users.selectedUser,
}),
(dispatch) => ({
onClick: (user) => dispatch({ type: actions.USER_SELECTED, payload: user }),
onClickUser: (user) => dispatch({ type: actions.USER_SELECTED, payload: user }),
})
)(Table);


export const UserDataConnected = connect(
(state) => ({
loading: state.userData.loading,
userName: state.userData.data.fullName,
age: state.userData.data.age,
})
)(UserData)
2 changes: 2 additions & 0 deletions src/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { combineReducers } from 'redux';

import users from './users';
import userData from './userData';

export default combineReducers({
userData,
users,
})

31 changes: 31 additions & 0 deletions src/reducers/userData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import actions from '../actions';

const initState = {
data: {},
loading: false,
error: null,
}

export default function(state = initState, action) {
switch (action.type) {
case actions.USER_INFO_ING:
return {
...initState,
loading: true,
}
case actions.USER_INFO_SUCCESS:
return {
...state,
loading: false,
data: action.payload,
}
case actions.USER_INFO_FAIL:
return {
...state,
loading: false,
error: action.error,
}
default:
return state;
}
}
30 changes: 27 additions & 3 deletions src/root.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
import React from 'react';
import { connect } from 'react-redux';
import actions from './actions';
import {
Table,
} from './components.jsx';
TableConnected,
UserDataConnected,
} from './containers';

export default function() { return (<div>app</div>); };
class Root extends React.Component {
componentDidMount() {
this.props.getUsers();
// this.props.init();
}
render() {
return (
<div>
<TableConnected />
<UserDataConnected />
{/*<button onClick={this.props.cancelRequest}>CANCEL</button>*/}
</div>);
}
};

export default connect(null,
(dispatch) => ({
getUsers: () => dispatch({ type: actions.USERS_FETCH_ING }),
// init: () => dispatch({ type: actions.INIT }),
// cancelRequest: () => dispatch({ type: actions.CANCEL_INFO_FETCH }),
})
)(Root);
32 changes: 30 additions & 2 deletions src/sagas.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { takeLatest, takeEvery } from 'redux-saga';
import { put, select, call } from 'redux-saga/effects';
import { put, select, call, take, race } from 'redux-saga/effects';
import api from './services';
import actions from './actions';
const WS_HOST = 'ws://localhost:2322'

// function* init() {
// yield put({ type: actions.USERS_FETCH_ING });
// yield put({ type: actions.WS_OPEN_PENDING, payload: WS_HOST})
// }

function* getUsers(action) {
try {
Expand All @@ -12,10 +18,32 @@ function* getUsers(action) {
}
}

function* selectUser(action) {
yield put({ type: actions.USER_INFO_ING, payload: action.payload.id })
}

function* getUserInfo(action) {
try {
const userInfo = yield call(api.getUserById, action.payload);
yield put({ type: actions.USER_INFO_SUCCESS, payload: userInfo.data })
} catch (error) {
yield put({ type: actions.USER_INFO_FAIL, error})
}
}

// function* getInfoCancellable(action) {
// const { cancel, fetch } = yield race({
// fetch: getUserInfo(action),
// cancel: take(actions.CANCEL_INFO_FETCH),
// })
// }

export default function* () {
yield [
takeEvery(actions.USERS_FETCH_ING, getUsers)
takeEvery(actions.USERS_FETCH_ING, getUsers),
takeEvery(actions.USER_INFO_ING, getUserInfo),
takeEvery(actions.USER_SELECTED, selectUser),
// takeEvery(actions.USER_INFO_ING, getInfoCancellable),
// takeLatest(actions.INIT, init),
]
}
27 changes: 27 additions & 0 deletions src/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,31 @@ export default {
getUsers() {
return axios.get('/users');
},
getUserById(id) {
return axios.get(`/user/${id}`);
},
ws: {
open(hostname) {
const ws = new WebSocket(hostname);

return new Promise((resolve, reject) => {
ws.onopen = () => resolve(ws);
ws.onerror = (err) => {
reject(new Error(err));
};
});
},
onReceive(ws, cb) {
ws.onmessage = cb;
},
onClose(ws, cb) {
ws.onclose = cb;
},
send(ws, msg) {
ws.send(msg);
},
close(ws) {
ws.close();
},
},
}
29 changes: 26 additions & 3 deletions src/style.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
.users {
margin: auto;
display: flex;
font-family: OpenSans, sans-serif;
font-size: 40px;
font-weight: 400;
}

.user {
padding: 10px;
padding: 10px 20px;
cursor: pointer;
.selected {
background-color: #AAA;
&.selected {
background-color: #AAC366;
}
}
.userdata {
font-size: 40px;
font-family: OpenSans, sans-serif;
&.loading {
background-color: #ccc;
}
border: 1px solid #AAC366;
.name {
padding: 10px 5px;
}
.age {
padding: 5px;
}
}
button {
font-size: 40px;
padding: 10px;
margin: 30px auto;
}
Loading

0 comments on commit de0b7f7

Please sign in to comment.