diff --git a/browser/main/HomePage.js b/browser/main/HomePage.js index 3cdf401c..6273e0dd 100644 --- a/browser/main/HomePage.js +++ b/browser/main/HomePage.js @@ -10,6 +10,8 @@ import { findWhere, findIndex, pick } from 'lodash' import keygen from 'boost/keygen' import { NEW, refreshArticles } from './actions' import api from 'boost/api' +import auth from 'boost/auth' +import './socket' class HomePage extends React.Component { componentDidMount () { @@ -17,18 +19,18 @@ class HomePage extends React.Component { dispatch(switchUser(this.props.params.userId)) - let currentUser = JSON.parse(localStorage.getItem('currentUser')) + let currentUser = auth.user() let users = [currentUser].concat(currentUser.Teams) - users.forEach(user => { - api.fetchArticles(user.id) - .then(res => { - dispatch(refreshArticles(user.id, res.body)) - }) - .catch(err => { - if (err.status == null) throw err - console.error(err) - }) - }) + users.forEach(user => { + api.fetchArticles(user.id) + .then(res => { + dispatch(refreshArticles(user.id, res.body)) + }) + .catch(err => { + if (err.status == null) throw err + console.error(err) + }) + }) } componentWillReceiveProps (nextProps) { diff --git a/browser/main/HomePage/ArticleList.js b/browser/main/HomePage/ArticleList.js index 0d4b3eb7..eafc0abe 100644 --- a/browser/main/HomePage/ArticleList.js +++ b/browser/main/HomePage/ArticleList.js @@ -2,7 +2,7 @@ import React, { PropTypes } from 'react' import ProfileImage from 'boost/components/ProfileImage' import ModeIcon from 'boost/components/ModeIcon' import moment from 'moment' -import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchArticle, NEW } from '../actions' +import { switchArticle, NEW } from '../actions' export default class ArticleList extends React.Component { handleArticleClick (key) { @@ -13,16 +13,14 @@ export default class ArticleList extends React.Component { } render () { - let { status, articles, activeArticle } = this.props + let { articles, activeArticle } = this.props let articlesEl = articles.map(article => { - let tags = Array.isArray(article.Tags) && article.Tags.length > 0 ? article.Tags.map(tag => { - return ( - {tag.name} - ) - }) : ( - Not tagged yet - ) + let tags = Array.isArray(article.Tags) && article.Tags.length > 0 + ? article.Tags.map(tag => { + return ({tag.name}) + }) + : (Not tagged yet) return (
@@ -53,7 +51,6 @@ export default class ArticleList extends React.Component { } ArticleList.propTypes = { - status: PropTypes.shape(), articles: PropTypes.array, activeArticle: PropTypes.shape(), dispatch: PropTypes.func diff --git a/browser/main/LoginPage.js b/browser/main/LoginPage.js index a732e2b9..fc01825a 100644 --- a/browser/main/LoginPage.js +++ b/browser/main/LoginPage.js @@ -2,6 +2,7 @@ import React, { PropTypes } from 'react' import { Link } from 'react-router' import linkState from 'boost/linkState' import { login } from 'boost/api' +import auth from 'boost/auth' export default class LoginPage extends React.Component { constructor (props) { @@ -23,8 +24,8 @@ export default class LoginPage extends React.Component { }, function () { login(this.state.user) .then(res => { - localStorage.setItem('token', res.body.token) - localStorage.setItem('currentUser', JSON.stringify(res.body.user)) + let { user, token } = res.body + auth.user(user, token) this.props.history.pushState('home') }) @@ -34,12 +35,11 @@ export default class LoginPage extends React.Component { return this.setState({ error: { name: 'CunnectionRefused', - message: 'Can\'t connect to API server.' + message: 'Can\'t cznnect to API server.' }, isSending: false }) - } - else if (err.status != null) { + } else if (err.status != null) { return this.setState({ error: { name: err.response.body.name, diff --git a/browser/main/actions.js b/browser/main/actions.js index 1d469b22..76851c15 100644 --- a/browser/main/actions.js +++ b/browser/main/actions.js @@ -30,21 +30,21 @@ export function updateUser (user) { export function refreshArticles (userId, articles) { return { type: ARTICLE_REFRESH, - data: {userId, articles} + data: { userId, articles } } } export function updateArticle (userId, article) { return { type: ARTICLE_UPDATE, - data: {userId, article} + data: { userId, article } } } -export function destroyArticle (userId, articleId) { +export function destroyArticle (userId, articleKey) { return { type: ARTICLE_DESTROY, - data: { userId, articleId } + data: { userId, articleKey } } } @@ -70,9 +70,9 @@ export function switchMode (mode) { } } -export function switchArticle (articleId) { +export function switchArticle (articleKey) { return { type: SWITCH_ARTICLE, - data: articleId + data: articleKey } } diff --git a/browser/main/index.js b/browser/main/index.js index 2228cd8a..162bce74 100644 --- a/browser/main/index.js +++ b/browser/main/index.js @@ -1,18 +1,18 @@ import React from 'react' -import { createStore } from 'redux' import { Provider } from 'react-redux' -import { updateUser, refreshArticles } from './actions' -import reducer from './reducer' -import { fetchCurrentUser, fetchArticles } from 'boost/api' +import { updateUser } from './actions' +import { fetchCurrentUser } from 'boost/api' import { Router, Route, IndexRoute } from 'react-router' import MainPage from './MainPage' import LoginPage from './LoginPage' import SignupPage from './SignupPage' import HomePage from './HomePage' +import auth from 'boost/auth' +import store, { devToolElement } from './store' require('../styles/main/index.styl') function onlyUser (state, replaceState) { - var currentUser = JSON.parse(localStorage.getItem('currentUser')) + let currentUser = auth.user() if (currentUser == null) return replaceState('login', '/login') if (state.location.pathname === '/') return replaceState('user', '/users/' + currentUser.id) } @@ -26,24 +26,6 @@ let routes = ( ) -// with Dev -import { compose } from 'redux' -// Redux DevTools store enhancers -import { devTools, persistState } from 'redux-devtools' -// React components for Redux DevTools -import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react' - -let finalCreateStore = compose(devTools(), persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)))(createStore) -let store = finalCreateStore(reducer) -let devEl = ( - - - -) - -// On production -// let store = createStore(reducer) - let el = document.getElementById('content') React.render(( @@ -51,7 +33,7 @@ React.render(( {() => {routes}} - {devEl} + {devToolElement}
), el, function () { let loadingCover = document.getElementById('loadingCover') diff --git a/browser/main/reducer.js b/browser/main/reducer.js index 9fd4600b..25f3f0bf 100644 --- a/browser/main/reducer.js +++ b/browser/main/reducer.js @@ -1,17 +1,14 @@ import { combineReducers } from 'redux' import { findIndex } from 'lodash' import { SWITCH_USER, SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, USER_UPDATE, ARTICLE_REFRESH, ARTICLE_UPDATE, ARTICLE_DESTROY, IDLE_MODE, CREATE_MODE } from './actions' +import auth from 'boost/auth' const initialStatus = { mode: IDLE_MODE } -function getInitialCurrentUser () { - return JSON.parse(localStorage.getItem('currentUser')) -} - function getInitialArticles () { - let initialCurrentUser = getInitialCurrentUser() + let initialCurrentUser = auth.user() if (initialCurrentUser == null) return [] let teams = Array.isArray(initialCurrentUser.Teams) ? initialCurrentUser.Teams : [] @@ -29,10 +26,10 @@ function currentUser (state, action) { switch (action.type) { case USER_UPDATE: let user = action.data - localStorage.setItem('currentUser', JSON.stringify(user)) - return user + + return auth.user(user) default: - if (state == null) return getInitialCurrentUser() + if (state == null) return auth.user() return state } } @@ -83,7 +80,7 @@ function articles (state, action) { let teamKey = genKey(userId) let articles = JSON.parse(localStorage.getItem(teamKey)) - let targetIndex = findIndex(articles, _article => article.id === _article.id) + let targetIndex = findIndex(articles, _article => article.key === _article.key) if (targetIndex < 0) articles.unshift(article) else articles.splice(targetIndex, 1, article) @@ -93,11 +90,12 @@ function articles (state, action) { return state case ARTICLE_DESTROY: { - let { userId, articleId } = action.data + let { userId, articleKey } = action.data let teamKey = genKey(userId) let articles = JSON.parse(localStorage.getItem(teamKey)) - - let targetIndex = findIndex(articles, _article => articleId === _article.id) + console.log(articles) + console.log(articleKey) + let targetIndex = findIndex(articles, _article => articleKey === _article.key) if (targetIndex >= 0) articles.splice(targetIndex, 1) localStorage.setItem(teamKey, JSON.stringify(articles)) diff --git a/browser/main/socket.js b/browser/main/socket.js new file mode 100644 index 00000000..b52f442e --- /dev/null +++ b/browser/main/socket.js @@ -0,0 +1,44 @@ +import { API_URL } from '../../config' +import socketio from 'socket.io-client' +import auth from 'boost/auth' +import store from './store' +import { updateArticle, destroyArticle } from './actions' + +export const CONN = 'CONN' +export const ALERT = 'ALERT' +export const USER_UPDATE = 'USER_UPDATE' +export const ARTICLE_UPDATE = 'ARTICLE_UPDATE' +export const ARTICLE_DESTROY = 'ARTICLE_DESTROY' + +let io = socketio(API_URL) + +io.on(CONN, function (data) { + console.log('connected', data) + + let token = auth.token() + if (token != null) { + io.emit('JOIN', {token}) + } +}) + +io.on(ALERT, function (data) { + console.log(ALERT, data) +}) + +io.on(USER_UPDATE, function (data) { + console.log(USER_UPDATE, data) +}) + +io.on(ARTICLE_UPDATE, function (data) { + console.log(ARTICLE_UPDATE, data) + let { userId, article } = data + store.dispatch(updateArticle(userId, article)) +}) + +io.on(ARTICLE_DESTROY, function (data) { + console.log(ARTICLE_DESTROY, data) + let { userId, articleKey } = data + store.dispatch(destroyArticle(userId, articleKey)) +}) + +export default io diff --git a/browser/main/store.js b/browser/main/store.js new file mode 100644 index 00000000..f5ac1d3a --- /dev/null +++ b/browser/main/store.js @@ -0,0 +1,20 @@ +import React from 'react' +import reducer from './reducer' +import { createStore } from 'redux' +// Devtools +import { compose } from 'redux' +import { devTools, persistState } from 'redux-devtools' +import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react' + +let finalCreateStore = compose(devTools(), persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)))(createStore) +let store = finalCreateStore(reducer) + +export let devToolElement = ( + + + +) + +// let store = createStore(reducer) + +export default store diff --git a/browser/styles/main/HomeContainer/components/ArticleDetail.styl b/browser/styles/main/HomeContainer/components/ArticleDetail.styl index 5f068590..7d51bf03 100644 --- a/browser/styles/main/HomeContainer/components/ArticleDetail.styl +++ b/browser/styles/main/HomeContainer/components/ArticleDetail.styl @@ -38,7 +38,6 @@ noTagsColor = #999 .detailInfo height 70px width 100% - transition 0.1s font-size 12px position relative .left diff --git a/config.js b/config.js index 7d3ed42b..4dc15e99 100644 --- a/config.js +++ b/config.js @@ -1,5 +1,2 @@ -module.exports = { - // apiUrl: 'https://api.b00st.io/' - // apiUrl: 'https://api2.b00st.io/' - apiUrl: 'http://localhost:8000/' -} +export const API_URL = 'http://localhost:8000/' +// export API_URL 'https://api2.b00st.io/' diff --git a/lib/api.js b/lib/api.js index 1874b71c..6ca98e60 100644 --- a/lib/api.js +++ b/lib/api.js @@ -1,107 +1,111 @@ -var request = require('superagent-promise')(require('superagent'), Promise) -var apiUrl = require('../config').apiUrl +import superagent from 'superagent' +import superagentPromise from 'superagent-promise' +import { API_URL } from '../config' +import auth from 'boost/auth' + +const request = superagentPromise(superagent, Promise) export function login (input) { return request - .post(apiUrl + 'auth/login') + .post(API_URL + 'auth/login') .send(input) } export function signup (input) { return request - .post(apiUrl + 'auth/register') + .post(API_URL + 'auth/register') .send(input) } export function fetchCurrentUser () { return request - .get(apiUrl + 'auth/user') + .get(API_URL + 'auth/user') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) } export function fetchArticles (userId) { return request - .get(apiUrl + 'teams/' + userId + '/articles') + .get(API_URL + 'teams/' + userId + '/articles') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) } export function createArticle (input) { return request - .post(apiUrl + 'articles/') + .post(API_URL + 'articles/') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function saveArticle (input) { return request - .put(apiUrl + 'articles/' + input.id) + .put(API_URL + 'articles/' + input.id) .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function destroyArticle (articleId) { return request - .del(apiUrl + 'articles/' + articleId) + .del(API_URL + 'articles/' + articleId) .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) } export function createTeam (input) { return request - .post(apiUrl + 'teams') + .post(API_URL + 'teams') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function searchUser (key) { return request - .get(apiUrl + 'search/users') + .get(API_URL + 'search/users') .query({key: key}) } export function setMember (teamId, input) { return request - .post(apiUrl + 'teams/' + teamId + '/members') + .post(API_URL + 'teams/' + teamId + '/members') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function deleteMember (teamId, input) { return request - .del(apiUrl + 'teams/' + teamId + '/members') + .del(API_URL + 'teams/' + teamId + '/members') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function createFolder (input) { return request - .post(apiUrl + 'folders/') + .post(API_URL + 'folders/') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } export function sendEmail (input) { return request - .post(apiUrl + 'mail') + .post(API_URL + 'mail') .set({ - Authorization: 'Bearer ' + localStorage.getItem('token') + Authorization: 'Bearer ' + auth.token() }) .send(input) } diff --git a/lib/auth.js b/lib/auth.js new file mode 100644 index 00000000..4f248250 --- /dev/null +++ b/lib/auth.js @@ -0,0 +1,34 @@ +// initial value +var currentUser = JSON.parse(localStorage.getItem('currentUser')) +var currentToken = localStorage.getItem('token') + +function user (user, newToken) { + if (user != null) { + localStorage.setItem('currentUser', JSON.stringify(user)) + currentUser = user + } + + if (newToken != null) { + localStorage.setItem('token', newToken) + currentToken = newToken + } + + return currentUser +} + +function token () { + return currentToken +} + +function clear () { + localStorage.removeItem('currentUser') + localStorage.removeItem('token') + currentUser = null + currentToken = null +} + +export default { + user, + token, + clear +}