diff --git a/package.json b/package.json index cd65a38e..0b9b0613 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "babel-preset-react-hmre": "^1.0.1", "babel-preset-stage-0": "^6.5.0", "body-parser": "^1.15.0", + "classnames": "^2.2.3", "codemirror": "^5.11.0", "cross-env": "^1.0.7", "css-loader": "^0.23.1", @@ -56,8 +57,11 @@ "react-redux": "^4.4.0", "react-router": "^2.0.0", "redux": "^3.3.1", + "redux-storage": "^3.0.0", + "redux-storage-engine-localstorage": "^1.0.0", "sass-loader": "^3.1.2", "style-loader": "^0.13.0", + "sw-toolbox": "^3.1.1", "to-markdown": "^2.0.1", "webpack": "^1.12.12", "webpack-dev-middleware": "^1.5.1", diff --git a/src/Actions/index.js b/src/Actions/index.js index 8b063477..5239e403 100644 --- a/src/Actions/index.js +++ b/src/Actions/index.js @@ -6,6 +6,7 @@ import keyMirror from 'fbjs/lib/keyMirror'; export const UPDATE_TEXT = 'UPDATE_TEXT'; export const TOGGLE_EDITORS = 'TOGGLE_EDITORS'; +export const TOGGLE_HISTORY_SIDEBAR = 'TOGGLE_HISTORY_SIDEBAR'; /* * Other Constants @@ -27,3 +28,7 @@ export function updateText(text, editor) { export function toggleEditors(toggledEditor) { return { type: TOGGLE_EDITORS, toggledEditor }; } + +export function toggleHistorySidebar() { + return { type: TOGGLE_HISTORY_SIDEBAR }; +} diff --git a/src/Components/Header/Header.js b/src/Components/Header/Header.js index 040aba12..c39821bf 100644 --- a/src/Components/Header/Header.js +++ b/src/Components/Header/Header.js @@ -1,12 +1,14 @@ import React from 'react'; import styles from './Header.scss'; +import classNames from 'classnames/bind'; +const cx = classNames.bind(styles); -const Header = ({ activeEditors, toggleEditors }) => { +const Header = ({ activeEditors, toggleEditors, showHistorySidebar, toggleHistorySidebar }) => { return (
Beautiful Atlas
-
+
{ className={ activeEditors.includes('TEXT') ? styles.active : '' } >Text
-
Versions
+
+ History +
); }; +Header.propTypes = { + showHistorySidebar: React.PropTypes.bool.isRequired, + toggleHistorySidebar: React.PropTypes.func.isRequired, +} + export default Header; diff --git a/src/Components/Header/Header.scss b/src/Components/Header/Header.scss index 157d54a3..9b9616ea 100644 --- a/src/Components/Header/Header.scss +++ b/src/Components/Header/Header.scss @@ -40,6 +40,13 @@ } } + .sidebar { + span { + margin-right: 12px; + cursor: pointer; + } + } + .active { text-decoration: underline; text-decoration-color: #fff; diff --git a/src/Components/HistorySidebar/HistorySidebar.js b/src/Components/HistorySidebar/HistorySidebar.js new file mode 100644 index 00000000..315fcdda --- /dev/null +++ b/src/Components/HistorySidebar/HistorySidebar.js @@ -0,0 +1,17 @@ +import React from 'react'; + +import styles from './HistorySidebar.scss'; + +class HistorySidebar extends React.Component { + render() { + return ( +
+
+ Revisions +
+
+ ); + } +}; + +export default HistorySidebar; diff --git a/src/Components/HistorySidebar/HistorySidebar.scss b/src/Components/HistorySidebar/HistorySidebar.scss new file mode 100644 index 00000000..fcdce15c --- /dev/null +++ b/src/Components/HistorySidebar/HistorySidebar.scss @@ -0,0 +1,12 @@ +.container { + width: 200px; + + background-color: #FBFBFB; + border-left: 1px solid #f0f0f0; + + font-size: 12px; +} + +.header { + padding: 20px 10px; +} \ No newline at end of file diff --git a/src/Components/HistorySidebar/index.js b/src/Components/HistorySidebar/index.js new file mode 100644 index 00000000..c4a6466c --- /dev/null +++ b/src/Components/HistorySidebar/index.js @@ -0,0 +1,2 @@ +import HistorySidebar from './HistorySidebar'; +export default HistorySidebar; diff --git a/src/Reducers/index.js b/src/Reducers/index.js index 77be62db..9b74a476 100644 --- a/src/Reducers/index.js +++ b/src/Reducers/index.js @@ -4,10 +4,11 @@ import { combineReducers } from 'redux'; import { UPDATE_TEXT, TOGGLE_EDITORS, + TOGGLE_HISTORY_SIDEBAR, ActiveEditors, } from '../Actions'; -function activeEditors(state = [ActiveEditors.MARKDOWN, ActiveEditors.TEXT], action) { +const activeEditors = (state = [ActiveEditors.MARKDOWN, ActiveEditors.TEXT], action) => { switch (action.type) { case TOGGLE_EDITORS: { const newState = _.xor(state, [action.toggledEditor]); @@ -22,7 +23,20 @@ function activeEditors(state = [ActiveEditors.MARKDOWN, ActiveEditors.TEXT], act } } -function text(state = '', action) { +const historySidebar = (state = { visible: false }, action) => { + switch (action.type) { + case TOGGLE_HISTORY_SIDEBAR: { + return { + ...state, + visible: !state.visible, + }; + } + default: + return state; + } +} + +const text = (state = '', action) => { switch (action.type) { case UPDATE_TEXT: return action.text; @@ -31,9 +45,8 @@ function text(state = '', action) { } } -const application = combineReducers({ +export default combineReducers({ activeEditors, + historySidebar, text, }); - -export default application; diff --git a/src/Views/App/App.js b/src/Views/App/App.js index 76a67630..c87b275d 100644 --- a/src/Views/App/App.js +++ b/src/Views/App/App.js @@ -4,7 +4,10 @@ import { connect } from 'react-redux'; import 'normalize.css/normalize.css'; import styles from './App.scss'; -import { toggleEditors } from '../../Actions'; +import { + toggleEditors, + toggleHistorySidebar, + } from '../../Actions'; import Header from '../../Components/Header'; @@ -13,17 +16,18 @@ import Auth from '../../Utils/Auth'; class App extends Component { static propTypes = { children: React.PropTypes.element, - activeEditors: React.PropTypes.isRequired, + activeEditors: React.PropTypes.array.isRequired, toggleEditors: React.PropTypes.func.isRequired, + showHistorySidebar: React.PropTypes.bool.isRequired, + toggleHistorySidebar: React.PropTypes.func.isRequired, } - static defaultProps = {} - state = { loggedIn: Auth.loggedIn(), } componentWillMount = () => { + console.log(this.props); Auth.onChange = this.updateAuth; } @@ -44,6 +48,8 @@ class App extends Component {
{ this.props.children } @@ -56,6 +62,7 @@ class App extends Component { const mapStateToProps = (state) => { return { activeEditors: state.activeEditors, + showHistorySidebar: state.historySidebar.visible, }; }; @@ -64,6 +71,9 @@ const mapDispatchToProps = (dispatch) => { toggleEditors: (toggledEditor) => { dispatch(toggleEditors(toggledEditor)); }, + toggleHistorySidebar: () => { + dispatch(toggleHistorySidebar()); + } }; }; diff --git a/src/Views/Dashboard/Dashboard.js b/src/Views/Dashboard/Dashboard.js index 0f92efc8..8ba970a1 100644 --- a/src/Views/Dashboard/Dashboard.js +++ b/src/Views/Dashboard/Dashboard.js @@ -3,6 +3,7 @@ import { connect } from 'react-redux'; import MarkdownEditor from '../../Components/MarkdownEditor'; import TextEditor from '../../Components/TextEditor'; +import HistorySidebar from '../../Components/HistorySidebar'; import { toMarkdown } from '../../Utils/Markdown'; import { updateText } from '../../Actions'; @@ -14,7 +15,8 @@ class Dashboard extends Component { editMarkdown: React.PropTypes.func.isRequired, editText: React.PropTypes.func.isRequired, text: React.PropTypes.string, - activeEditors: React.PropTypes.array, + activeEditors: React.PropTypes.arrayOf(React.PropTypes.string), + showHistorySidebar: React.PropTypes.bool.isRequired, } // componentDidMount = () => { @@ -25,6 +27,7 @@ class Dashboard extends Component { // } render() { + console.log(this.props.showHistorySidebar); const activeEditors = this.props.activeEditors; return ( @@ -47,6 +50,13 @@ class Dashboard extends Component {
) : null } + { + this.props.showHistorySidebar ? +
+ +
+ : null + }
); } @@ -57,6 +67,7 @@ const mapStateToProps = (state) => { text: state.text, editor: state.editor, activeEditors: state.activeEditors, + showHistorySidebar: state.historySidebar.visible, }; }; diff --git a/src/index.js b/src/index.js index 1d248aad..c324c4d1 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,9 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { Router, Route } from 'react-router'; -import { createStore, compose } from 'redux'; +import { createStore, applyMiddleware, compose } from 'redux'; +import * as storage from 'redux-storage'; +import createEngine from 'redux-storage-engine-localstorage'; import History from './Utils/History'; import Auth from './Utils/Auth'; @@ -13,12 +15,17 @@ import App from './Views/App'; import Login from './Views/Login'; import Dashboard from './Views/Dashboard'; -const store = createStore( - reducers, - compose( - window.devToolsExtension ? window.devToolsExtension() : f => f - ) -); +const reducer = storage.reducer(reducers); +const engine = createEngine('atlas-store'); +const storageMiddleware = storage.createMiddleware(engine); + +const createStoreWithMiddleware = applyMiddleware(storageMiddleware)(createStore); +const store = createStoreWithMiddleware(reducer); + +const load = storage.createLoader(engine); +load(store) + .then((newState) => console.log('Loaded state:', newState)) + .catch(() => console.log('Failed to load previous state')); function requireAuth(nextState, replace) { if (!Auth.loggedIn()) {