diff --git a/client/assets/scss/main.scss b/client/assets/scss/main.scss index 60c5387..f92c289 100644 --- a/client/assets/scss/main.scss +++ b/client/assets/scss/main.scss @@ -11,19 +11,6 @@ body{ display: flex; box-sizing: padding-box; padding: 1em calc(50% - 997px / 2); - - @media (max-width: 768px) { /* phone */ - padding: 1em calc(50% - 736px / 2); - } - - @media (min-width: 992px) { /* tablet */ - padding: 1em calc(50% - 960px / 2); - } - - @media (min-width: 1200px) { /* desktop */ - padding: 1em calc(50% - 1168px / 2); - } - &:before, &:after { content: " "; width: 1em; } } } diff --git a/client/js/app.js b/client/js/app.js new file mode 100644 index 0000000..ac75525 --- /dev/null +++ b/client/js/app.js @@ -0,0 +1,47 @@ +//react imports +import React from 'react'; +import ReactDOM from 'react-dom'; +import {Router, Route, IndexRoute} from 'react-router'; + +//redux imports +import {bindActionCreators} from 'redux'; +import {connect, Provider} from 'react-redux'; +import store, {history} from './redux/store'; + +//import actions +import * as actions from './redux/actions'; + +import Index from './pages/Index'; + +class Main extends React.Component{ + render(){ + return( +
{React.cloneElement(this.props.children, this.props)}
+ ); + } +} + +function mapStateToProps(state){ + return { + redux: state.reducer + } +} + +function mapDispatchToProps(dispatch){ + return{ + actions: bindActionCreators(actions, dispatch) + } +} + +const App = connect(mapStateToProps, mapDispatchToProps)(Main); + +ReactDOM.render(( + + + + + + + + +),document.getElementById('app')); \ No newline at end of file diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js new file mode 100644 index 0000000..d27928d --- /dev/null +++ b/client/js/components/Preview.js @@ -0,0 +1,30 @@ +import React from 'react'; +import Link from 'react-router'; + +export default class Preview extends React.Component{ + + insertPosts(posts){ + let elements = []; + for (let i in posts){ + elements.push( +
+

{posts[i].title}

+

{posts[i].date}

+

{posts[i].intro}

+
+ ); + } + + return elements; + } + + render(){ + const posts = this.props.posts; + + return ( +
+ {posts.length > 0 ? this.insertPosts(posts): ""} +
+ ); + } +} \ No newline at end of file diff --git a/client/js/components/Previews.js b/client/js/components/Previews.js deleted file mode 100644 index 375b464..0000000 --- a/client/js/components/Previews.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -export default class Previews extends React.Component{ - - insertPosts(){ - let posts = []; - - for (let i = 0; i < 10; i++){ - posts.push(

This is a test push {i}

); - } - - return posts; - } - - render(){ - return ( -
{this.insertPosts()}
- ); - } -} \ No newline at end of file diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 53ecae6..7b96b36 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -2,7 +2,7 @@ import React from 'react'; //components import Header from '../components/Header'; -import Previews from '../components/Previews'; +import Preview from '../components/Preview'; import Footer from '../components/Footer'; import Sidebar from '../components/Sidebar'; @@ -11,16 +11,20 @@ import '../../assets/css/normalize.css'; import '../../assets/scss/main.scss'; export default class Index extends React.Component{ + componentDidMount(){ + this.props.actions.fetchPreview(); + } + render(){ return( -
-
-
- - +
+
+
+ + +
+
-
-
); } } \ No newline at end of file diff --git a/client/js/redux/actions.js b/client/js/redux/actions.js new file mode 100644 index 0000000..4e2309c --- /dev/null +++ b/client/js/redux/actions.js @@ -0,0 +1,23 @@ +import * as types from "./constants"; + +function initPreview(posts){ + return{ + type: types.INIT_PREVIEW, + posts + } +} + +//using redux-thunk we can modify actions before they get called +//in this case we can send the http request here rather in the react component +export function fetchPreview(){ + return (dispatch) => { + return fetch('/metadata.json') + .then(response => response.json()) + .then(json => { + dispatch(initPreview(json)); + }) + .catch(error => { + console.log(error); + }); + } +} \ No newline at end of file diff --git a/client/js/redux/constants.js b/client/js/redux/constants.js new file mode 100644 index 0000000..cccdbc4 --- /dev/null +++ b/client/js/redux/constants.js @@ -0,0 +1,3 @@ +//constants +export const INIT_PREVIEW = 'INIT_PREVIEW'; +export const FILTER_PREVIEW = 'FILTER_PREVIEW'; \ No newline at end of file diff --git a/client/js/redux/reducers.js b/client/js/redux/reducers.js new file mode 100644 index 0000000..2e678e6 --- /dev/null +++ b/client/js/redux/reducers.js @@ -0,0 +1,37 @@ +//just using one reducer - use combineReducers from redux to modularize things +import {combineReducers} from 'redux'; +import {routerReducer} from 'react-router-redux'; + +//import typs +import * as types from './constants'; + +//defaults - +const defaultState = { + preview: {posts: []}, + filteredPreview: {posts: []} +}; + +//default reducer +function reducer(state = defaultState, action){ + //every reducer gets called when an action is called - we check for the type to modify our state accordingly + switch (action.type){ + case types.INIT_PREVIEW: + return Object.assign({}, state, { + preview: Object.assign({}, state.preview, action.posts) + }); + case types.FILTER_PREVIEW: + return Object.assign({}, state, { + filteredPreview: Object.assign({}, state.filteredPreview, action.posts) + }) + } + + //return present state if no actions get called + return state; +} + +const allReducers = combineReducers({ + reducer, + routing: routerReducer +}); + +export default allReducers; \ No newline at end of file diff --git a/client/js/redux/store.js b/client/js/redux/store.js new file mode 100644 index 0000000..9930ebe --- /dev/null +++ b/client/js/redux/store.js @@ -0,0 +1,15 @@ +import {applyMiddleware, createStore} from 'redux'; +import {syncHistoryWithStore} from 'react-router-redux'; +import {browserHistory} from 'react-router'; +import thunk from 'redux-thunk'; + +import reducers from './reducers'; + +const middleware = applyMiddleware(thunk); + +//create the new store with default state as an empty object +const store = createStore(reducers, {}, middleware); + +export const history = syncHistoryWithStore(browserHistory, store); + +export default store; \ No newline at end of file diff --git a/client/js/routes.js b/client/js/routes.js deleted file mode 100644 index 0b81c15..0000000 --- a/client/js/routes.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import {browserHistory, Router, Route, IndexRoute} from 'react-router'; - -import Index from './pages/Index'; - -class App extends React.Component{ - render(){ - return( -
{React.cloneElement(this.props.children, this.props)}
- ); - } -} - -ReactDOM.render(( - - - - - - -),document.getElementById('app')); \ No newline at end of file diff --git a/metadata.js b/metadata.js index eebef7e..232d667 100644 --- a/metadata.js +++ b/metadata.js @@ -43,7 +43,6 @@ function parse_dir(dir, folder_name){ title: marked('

' + tokens[0].text + '

'), intro: marked(tokens[1].text) } - console.log(marked(file)); json.posts.push(temp); } } diff --git a/package.json b/package.json index 7fe6668..8c8aaee 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,11 @@ "node-sass": "^3.8.0", "react": "^15.3.0", "react-dom": "^15.3.0", + "react-redux": "^4.4.5", "react-router": "^2.6.1", + "react-router-redux": "^4.0.5", + "redux": "^3.5.2", + "redux-thunk": "^2.1.0", "sass-loader": "^4.0.0", "style-loader": "^0.13.1", "url-loader": "^0.5.7", diff --git a/webpack.config.js b/webpack.config.js index 60890ac..67b9ad1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,7 +5,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { devtool: debug ? "inline-sourcemap" : null, - entry: "./client/js/routes.js", + entry: "./client/js/app.js", module: { loaders: [ {